Notify IMS Call info via CallAttributesListener
Notify IMS call type & IMS call ID through CallAttributes.
List of CallAttributes mapped to whole calls will be passed to the
listener.
Bug: 242928210
Test: atest FrameworksTelephonyTests, Device test b/260350954
Change-Id: I1584524cec49af0694f691efdcbec4210f06e09a
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2e0c76a..72bff0f 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12810,14 +12810,14 @@
method @NonNull public android.telephony.BarringInfo createLocationInfoSanitizedCopy();
}
- public final class CallAttributes implements android.os.Parcelable {
- ctor public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
- method public int describeContents();
- method @NonNull public android.telephony.CallQuality getCallQuality();
- method public int getNetworkType();
- method @NonNull public android.telephony.PreciseCallState getPreciseCallState();
- method public void writeToParcel(android.os.Parcel, int);
- field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
+ @Deprecated public final class CallAttributes implements android.os.Parcelable {
+ ctor @Deprecated public CallAttributes(@NonNull android.telephony.PreciseCallState, int, @NonNull android.telephony.CallQuality);
+ method @Deprecated public int describeContents();
+ method @Deprecated @NonNull public android.telephony.CallQuality getCallQuality();
+ method @Deprecated public int getNetworkType();
+ method @Deprecated @NonNull public android.telephony.PreciseCallState getPreciseCallState();
+ method @Deprecated public void writeToParcel(android.os.Parcel, int);
+ field @Deprecated @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallAttributes> CREATOR;
}
public final class CallForwardingInfo implements android.os.Parcelable {
@@ -12897,6 +12897,28 @@
method @NonNull public android.telephony.CallQuality.Builder setUplinkCallQualityLevel(int);
}
+ public final class CallState implements android.os.Parcelable {
+ method public int describeContents();
+ method @Nullable public android.telephony.CallQuality getCallQuality();
+ method public int getCallState();
+ method public int getImsCallServiceType();
+ method @Nullable public String getImsCallSessionId();
+ method public int getImsCallType();
+ method public int getNetworkType();
+ method public void writeToParcel(@Nullable android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.telephony.CallState> CREATOR;
+ }
+
+ public static final class CallState.Builder {
+ ctor public CallState.Builder(int);
+ method @NonNull public android.telephony.CallState build();
+ method @NonNull public android.telephony.CallState.Builder setCallQuality(@Nullable android.telephony.CallQuality);
+ method @NonNull public android.telephony.CallState.Builder setImsCallServiceType(int);
+ method @NonNull public android.telephony.CallState.Builder setImsCallSessionId(@Nullable String);
+ method @NonNull public android.telephony.CallState.Builder setImsCallType(int);
+ method @NonNull public android.telephony.CallState.Builder setNetworkType(int);
+ }
+
public class CarrierConfigManager {
method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getDefaultCarrierServicePackageName();
method @NonNull public static android.os.PersistableBundle getDefaultConfig();
@@ -13647,7 +13669,8 @@
}
public static interface TelephonyCallback.CallAttributesListener {
- method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
+ method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
+ method @RequiresPermission(android.Manifest.permission.READ_PRECISE_PHONE_STATE) public default void onCallStatesChanged(@NonNull java.util.List<android.telephony.CallState>);
}
public static interface TelephonyCallback.DataEnabledListener {
@@ -14748,6 +14771,7 @@
field public static final int CALL_RESTRICT_CAUSE_HD = 3; // 0x3
field public static final int CALL_RESTRICT_CAUSE_NONE = 0; // 0x0
field public static final int CALL_RESTRICT_CAUSE_RAT = 1; // 0x1
+ field public static final int CALL_TYPE_NONE = 0; // 0x0
field public static final int CALL_TYPE_VIDEO_N_VOICE = 3; // 0x3
field public static final int CALL_TYPE_VOICE = 2; // 0x2
field public static final int CALL_TYPE_VOICE_N_VIDEO = 1; // 0x1
diff --git a/core/java/android/telephony/PhoneStateListener.java b/core/java/android/telephony/PhoneStateListener.java
index e5c9adb..dded76c 100644
--- a/core/java/android/telephony/PhoneStateListener.java
+++ b/core/java/android/telephony/PhoneStateListener.java
@@ -26,7 +26,6 @@
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.Looper;
-import android.telephony.Annotation.CallState;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
@@ -726,7 +725,7 @@
*/
@Deprecated
@RequiresPermission(value = android.Manifest.permission.READ_PHONE_STATE, conditional = true)
- public void onCallStateChanged(@CallState int state, String phoneNumber) {
+ public void onCallStateChanged(@Annotation.CallState int state, String phoneNumber) {
// default implementation empty
}
@@ -1569,12 +1568,48 @@
() -> mExecutor.execute(() -> psl.onRadioPowerStateChanged(state)));
}
- public void onCallAttributesChanged(CallAttributes callAttributes) {
+ public void onCallStatesChanged(List<CallState> callStateList) {
PhoneStateListener psl = mPhoneStateListenerWeakRef.get();
if (psl == null) return;
+ if (callStateList == null) return;
+ CallAttributes ca;
+ if (callStateList.isEmpty()) {
+ ca = new CallAttributes(
+ new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_IDLE,
+ PreciseCallState.PRECISE_CALL_STATE_IDLE,
+ PreciseCallState.PRECISE_CALL_STATE_IDLE,
+ DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality());
+ } else {
+ int foregroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ int backgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ int ringingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ for (CallState cs : callStateList) {
+ switch (cs.getCallClassification()) {
+ case CallState.CALL_CLASSIFICATION_FOREGROUND:
+ foregroundCallState = cs.getCallState();
+ break;
+ case CallState.CALL_CLASSIFICATION_BACKGROUND:
+ backgroundCallState = cs.getCallState();
+ break;
+ case CallState.CALL_CLASSIFICATION_RINGING:
+ ringingCallState = cs.getCallState();
+ break;
+ default:
+ break;
+ }
+ }
+ ca = new CallAttributes(
+ new PreciseCallState(
+ ringingCallState, foregroundCallState, backgroundCallState,
+ DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
+ callStateList.get(0).getNetworkType(),
+ callStateList.get(0).getCallQuality());
+ }
Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> psl.onCallAttributesChanged(callAttributes)));
+ () -> mExecutor.execute(
+ () -> psl.onCallAttributesChanged(ca)));
}
public void onActiveDataSubIdChanged(int subId) {
diff --git a/core/java/android/telephony/TelephonyCallback.java b/core/java/android/telephony/TelephonyCallback.java
index e8960b8..257f3b7 100644
--- a/core/java/android/telephony/TelephonyCallback.java
+++ b/core/java/android/telephony/TelephonyCallback.java
@@ -27,6 +27,7 @@
import android.os.Build;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.ImsReasonInfo;
+import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.IPhoneStateListener;
@@ -62,7 +63,7 @@
* appropriate sub-interfaces.
*/
public class TelephonyCallback {
-
+ private static final String LOG_TAG = "TelephonyCallback";
/**
* Experiment flag to set the per-pid registration limit for TelephonyCallback
*
@@ -1332,7 +1333,9 @@
@SystemApi
public interface CallAttributesListener {
/**
- * Callback invoked when the call attributes changes on the registered subscription.
+ * Callback invoked when the call attributes changes on the active call on the registered
+ * subscription. If the user swaps between a foreground and background call the call
+ * attributes will be reported for the active call only.
* Note, the registration subscription ID comes from {@link TelephonyManager} object
* which registers TelephonyCallback by
* {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}.
@@ -1346,9 +1349,77 @@
* {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
*
* @param callAttributes the call attributes
+ * @deprecated Use onCallStatesChanged({@link List<CallState>}) to get each of call
+ * state for all ongoing calls on the subscription.
*/
@RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
- void onCallAttributesChanged(@NonNull CallAttributes callAttributes);
+ @Deprecated
+ default void onCallAttributesChanged(@NonNull CallAttributes callAttributes) {
+ Log.w(LOG_TAG, "onCallAttributesChanged(List<CallState>) should be "
+ + "overridden.");
+ }
+
+ /**
+ * Callback invoked when the call attributes changes on the ongoing calls on the registered
+ * subscription. If there are 1 foreground and 1 background call, Two {@link CallState}
+ * will be passed.
+ * Note, the registration subscription ID comes from {@link TelephonyManager} object
+ * which registers TelephonyCallback by
+ * {@link TelephonyManager#registerTelephonyCallback(Executor, TelephonyCallback)}.
+ * If this TelephonyManager object was created with
+ * {@link TelephonyManager#createForSubscriptionId(int)}, then the callback applies to the
+ * subscription ID. Otherwise, this callback applies to
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}.
+ * In the event that there are no active(state is not
+ * {@link PreciseCallState#PRECISE_CALL_STATE_IDLE}) calls, this API will report empty list.
+ *
+ * The calling app should have carrier privileges
+ * (see {@link TelephonyManager#hasCarrierPrivileges}) if it does not have the
+ * {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE}.
+ *
+ * @param callStateList the list of call states for each ongoing call. If there are
+ * a active call and a holding call, 1 call attributes for
+ * {@link PreciseCallState#PRECISE_CALL_STATE_ACTIVE} and another
+ * for {@link PreciseCallState#PRECISE_CALL_STATE_HOLDING}
+ * will be in this list.
+ */
+ // Added as default for backward compatibility
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
+ default void onCallStatesChanged(@NonNull List<CallState> callStateList) {
+ if (callStateList.size() > 0) {
+ int foregroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ int backgroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ int ringingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
+ for (CallState cs : callStateList) {
+ switch (cs.getCallClassification()) {
+ case CallState.CALL_CLASSIFICATION_FOREGROUND:
+ foregroundCallState = cs.getCallState();
+ break;
+ case CallState.CALL_CLASSIFICATION_BACKGROUND:
+ backgroundCallState = cs.getCallState();
+ break;
+ case CallState.CALL_CLASSIFICATION_RINGING:
+ ringingCallState = cs.getCallState();
+ break;
+ default:
+ break;
+ }
+ }
+ onCallAttributesChanged(new CallAttributes(
+ new PreciseCallState(
+ ringingCallState, foregroundCallState, backgroundCallState,
+ DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
+ callStateList.get(0).getNetworkType(),
+ callStateList.get(0).getCallQuality()));
+ } else {
+ onCallAttributesChanged(new CallAttributes(
+ new PreciseCallState(PreciseCallState.PRECISE_CALL_STATE_IDLE,
+ PreciseCallState.PRECISE_CALL_STATE_IDLE,
+ PreciseCallState.PRECISE_CALL_STATE_IDLE,
+ DisconnectCause.NOT_VALID, PreciseDisconnectCause.NOT_VALID),
+ TelephonyManager.NETWORK_TYPE_UNKNOWN, new CallQuality()));
+ }
+ }
}
/**
@@ -1702,14 +1773,13 @@
() -> mExecutor.execute(() -> listener.onRadioPowerStateChanged(state)));
}
- public void onCallAttributesChanged(CallAttributes callAttributes) {
+ public void onCallStatesChanged(List<CallState> callStateList) {
CallAttributesListener listener =
(CallAttributesListener) mTelephonyCallbackWeakRef.get();
if (listener == null) return;
Binder.withCleanCallingIdentity(
- () -> mExecutor.execute(() -> listener.onCallAttributesChanged(
- callAttributes)));
+ () -> mExecutor.execute(() -> listener.onCallStatesChanged(callStateList)));
}
public void onActiveDataSubIdChanged(int subId) {
diff --git a/core/java/android/telephony/TelephonyRegistryManager.java b/core/java/android/telephony/TelephonyRegistryManager.java
index a3696e3..0a1538de 100644
--- a/core/java/android/telephony/TelephonyRegistryManager.java
+++ b/core/java/android/telephony/TelephonyRegistryManager.java
@@ -32,13 +32,13 @@
import android.telephony.Annotation.DataActivityType;
import android.telephony.Annotation.DisconnectCauses;
import android.telephony.Annotation.NetworkType;
-import android.telephony.Annotation.PreciseCallStates;
import android.telephony.Annotation.PreciseDisconnectCauses;
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SimActivationState;
import android.telephony.Annotation.SrvccState;
import android.telephony.TelephonyManager.CarrierPrivilegesCallback;
import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsReasonInfo;
import android.util.ArraySet;
import android.util.Log;
@@ -741,17 +741,20 @@
* @param slotIndex for which precise call state changed. Can be derived from subId except when
* subId is invalid.
* @param subId for which precise call state changed.
- * @param ringCallPreciseState ringCall state.
- * @param foregroundCallPreciseState foreground call state.
- * @param backgroundCallPreciseState background call state.
+ * @param callStates Array of PreciseCallState of foreground, background & ringing calls.
+ * @param imsCallIds Array of IMS call session ID{@link ImsCallSession#getCallId} for
+ * ringing, foreground & background calls.
+ * @param imsServiceTypes Array of IMS call service type for ringing, foreground &
+ * background calls.
+ * @param imsCallTypes Array of IMS call type for ringing, foreground & background calls.
*/
public void notifyPreciseCallState(int slotIndex, int subId,
- @PreciseCallStates int ringCallPreciseState,
- @PreciseCallStates int foregroundCallPreciseState,
- @PreciseCallStates int backgroundCallPreciseState) {
+ @Annotation.PreciseCallStates int[] callStates, String[] imsCallIds,
+ @Annotation.ImsCallServiceType int[] imsServiceTypes,
+ @Annotation.ImsCallType int[] imsCallTypes) {
try {
- sRegistry.notifyPreciseCallState(slotIndex, subId, ringCallPreciseState,
- foregroundCallPreciseState, backgroundCallPreciseState);
+ sRegistry.notifyPreciseCallState(slotIndex, subId, callStates,
+ imsCallIds, imsServiceTypes, imsCallTypes);
} catch (RemoteException ex) {
// system process is dead
throw ex.rethrowFromSystemServer();
diff --git a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
index 4b1753a..9cb2e68 100644
--- a/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/core/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -17,7 +17,7 @@
package com.android.internal.telephony;
import android.telephony.BarringInfo;
-import android.telephony.CallAttributes;
+import android.telephony.CallState;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.DataConnectionRealTimeInfo;
@@ -62,7 +62,7 @@
void onPhoneCapabilityChanged(in PhoneCapability capability);
void onActiveDataSubIdChanged(in int subId);
void onRadioPowerStateChanged(in int state);
- void onCallAttributesChanged(in CallAttributes callAttributes);
+ void onCallStatesChanged(in List<CallState> callStateList);
@SuppressWarnings(value={"untyped-collection"})
void onEmergencyNumberListChanged(in Map emergencyNumberList);
void onOutgoingEmergencyCall(in EmergencyNumber placedEmergencyNumber, int subscriptionId);
diff --git a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index c7fa757..7ba2686 100644
--- a/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/core/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -66,8 +66,8 @@
void notifyCellLocationForSubscriber(in int subId, in CellIdentity cellLocation);
@UnsupportedAppUsage
void notifyCellInfo(in List<CellInfo> cellInfo);
- void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
- int foregroundCallState, int backgroundCallState);
+ void notifyPreciseCallState(int phoneId, int subId, in int[] callStates, in String[] imsCallIds,
+ in int[] imsCallServiceTypes, in int[] imsCallTypes);
void notifyDisconnectCause(int phoneId, int subId, int disconnectCause,
int preciseDisconnectCause);
void notifyCellInfoForSubscriber(in int subId, in List<CellInfo> cellInfo);
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index ca86021c..bd90d85 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -52,8 +52,8 @@
import android.telephony.Annotation.RadioPowerState;
import android.telephony.Annotation.SrvccState;
import android.telephony.BarringInfo;
-import android.telephony.CallAttributes;
import android.telephony.CallQuality;
+import android.telephony.CallState;
import android.telephony.CellIdentity;
import android.telephony.CellInfo;
import android.telephony.CellSignalStrength;
@@ -82,6 +82,7 @@
import android.telephony.TelephonyManager;
import android.telephony.data.ApnSetting;
import android.telephony.emergency.EmergencyNumber;
+import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsReasonInfo;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -349,9 +350,9 @@
private CallQuality[] mCallQuality;
- private CallAttributes[] mCallAttributes;
+ private ArrayList<List<CallState>> mCallStateLists;
- // network type of the call associated with the mCallAttributes and mCallQuality
+ // network type of the call associated with the mCallStateLists and mCallQuality
private int[] mCallNetworkType;
private int[] mSrvccState;
@@ -687,7 +688,6 @@
mCallPreciseDisconnectCause = copyOf(mCallPreciseDisconnectCause, mNumPhones);
mCallQuality = copyOf(mCallQuality, mNumPhones);
mCallNetworkType = copyOf(mCallNetworkType, mNumPhones);
- mCallAttributes = copyOf(mCallAttributes, mNumPhones);
mOutgoingCallEmergencyNumber = copyOf(mOutgoingCallEmergencyNumber, mNumPhones);
mOutgoingSmsEmergencyNumber = copyOf(mOutgoingSmsEmergencyNumber, mNumPhones);
mTelephonyDisplayInfos = copyOf(mTelephonyDisplayInfos, mNumPhones);
@@ -707,6 +707,7 @@
cutListToSize(mLinkCapacityEstimateLists, mNumPhones);
cutListToSize(mCarrierPrivilegeStates, mNumPhones);
cutListToSize(mCarrierServiceStates, mNumPhones);
+ cutListToSize(mCallStateLists, mNumPhones);
return;
}
@@ -730,8 +731,7 @@
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
+ mCallStateLists.add(i, new ArrayList<>());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -799,7 +799,7 @@
mCallPreciseDisconnectCause = new int[numPhones];
mCallQuality = new CallQuality[numPhones];
mCallNetworkType = new int[numPhones];
- mCallAttributes = new CallAttributes[numPhones];
+ mCallStateLists = new ArrayList<>();
mPreciseDataConnectionStates = new ArrayList<>();
mCellInfo = new ArrayList<>(numPhones);
mImsReasonInfo = new ArrayList<>();
@@ -837,8 +837,7 @@
mCallDisconnectCause[i] = DisconnectCause.NOT_VALID;
mCallPreciseDisconnectCause[i] = PreciseDisconnectCause.NOT_VALID;
mCallQuality[i] = createCallQuality();
- mCallAttributes[i] = new CallAttributes(createPreciseCallState(),
- TelephonyManager.NETWORK_TYPE_UNKNOWN, createCallQuality());
+ mCallStateLists.add(i, new ArrayList<>());
mCallNetworkType[i] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mPreciseCallState[i] = createPreciseCallState();
mRingingCallState[i] = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -1336,7 +1335,7 @@
}
if (events.contains(TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)) {
try {
- r.callback.onCallAttributesChanged(mCallAttributes[r.phoneId]);
+ r.callback.onCallStatesChanged(mCallStateLists.get(r.phoneId));
} catch (RemoteException ex) {
remove(r.binder);
}
@@ -2171,11 +2170,30 @@
}
}
- public void notifyPreciseCallState(int phoneId, int subId, int ringingCallState,
- int foregroundCallState, int backgroundCallState) {
+ /**
+ * Send a notification to registrants that the precise call state has changed.
+ *
+ * @param phoneId the phoneId carrying the data connection
+ * @param subId the subscriptionId for the data connection
+ * @param callStates Array of PreciseCallState of foreground, background & ringing calls.
+ * @param imsCallIds Array of IMS call session ID{@link ImsCallSession#getCallId()} for
+ * ringing, foreground & background calls.
+ * @param imsServiceTypes Array of IMS call service type for ringing, foreground &
+ * background calls.
+ * @param imsCallTypes Array of IMS call type for ringing, foreground & background calls.
+ */
+ public void notifyPreciseCallState(int phoneId, int subId,
+ @Annotation.PreciseCallStates int[] callStates, String[] imsCallIds,
+ @Annotation.ImsCallServiceType int[] imsServiceTypes,
+ @Annotation.ImsCallType int[] imsCallTypes) {
if (!checkNotifyPermission("notifyPreciseCallState()")) {
return;
}
+
+ int ringingCallState = callStates[CallState.CALL_CLASSIFICATION_RINGING];
+ int foregroundCallState = callStates[CallState.CALL_CLASSIFICATION_FOREGROUND];
+ int backgroundCallState = callStates[CallState.CALL_CLASSIFICATION_BACKGROUND];
+
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
mRingingCallState[phoneId] = ringingCallState;
@@ -2186,11 +2204,11 @@
backgroundCallState,
DisconnectCause.NOT_VALID,
PreciseDisconnectCause.NOT_VALID);
- boolean notifyCallAttributes = true;
+ boolean notifyCallState = true;
if (mCallQuality == null) {
log("notifyPreciseCallState: mCallQuality is null, "
+ "skipping call attributes");
- notifyCallAttributes = false;
+ notifyCallState = false;
} else {
// If the precise call state is no longer active, reset the call network type
// and call quality.
@@ -2199,8 +2217,65 @@
mCallNetworkType[phoneId] = TelephonyManager.NETWORK_TYPE_UNKNOWN;
mCallQuality[phoneId] = createCallQuality();
}
- mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
- mCallNetworkType[phoneId], mCallQuality[phoneId]);
+ mCallStateLists.get(phoneId).clear();
+ if (foregroundCallState != PreciseCallState.PRECISE_CALL_STATE_NOT_VALID
+ && foregroundCallState != PreciseCallState.PRECISE_CALL_STATE_IDLE) {
+ CallQuality callQuality = mCallQuality[phoneId];
+ CallState.Builder builder = new CallState.Builder(
+ callStates[CallState.CALL_CLASSIFICATION_FOREGROUND])
+ .setNetworkType(mCallNetworkType[phoneId])
+ .setCallQuality(callQuality)
+ .setCallClassification(
+ CallState.CALL_CLASSIFICATION_FOREGROUND);
+ if (imsCallIds != null && imsServiceTypes != null && imsCallTypes != null) {
+ builder = builder
+ .setImsCallSessionId(imsCallIds[
+ CallState.CALL_CLASSIFICATION_FOREGROUND])
+ .setImsCallServiceType(imsServiceTypes[
+ CallState.CALL_CLASSIFICATION_FOREGROUND])
+ .setImsCallType(imsCallTypes[
+ CallState.CALL_CLASSIFICATION_FOREGROUND]);
+ }
+ mCallStateLists.get(phoneId).add(builder.build());
+ }
+ if (backgroundCallState != PreciseCallState.PRECISE_CALL_STATE_NOT_VALID
+ && backgroundCallState != PreciseCallState.PRECISE_CALL_STATE_IDLE) {
+ CallState.Builder builder = new CallState.Builder(
+ callStates[CallState.CALL_CLASSIFICATION_BACKGROUND])
+ .setNetworkType(mCallNetworkType[phoneId])
+ .setCallQuality(createCallQuality())
+ .setCallClassification(
+ CallState.CALL_CLASSIFICATION_BACKGROUND);
+ if (imsCallIds != null && imsServiceTypes != null && imsCallTypes != null) {
+ builder = builder
+ .setImsCallSessionId(imsCallIds[
+ CallState.CALL_CLASSIFICATION_BACKGROUND])
+ .setImsCallServiceType(imsServiceTypes[
+ CallState.CALL_CLASSIFICATION_BACKGROUND])
+ .setImsCallType(imsCallTypes[
+ CallState.CALL_CLASSIFICATION_BACKGROUND]);
+ }
+ mCallStateLists.get(phoneId).add(builder.build());
+ }
+ if (ringingCallState != PreciseCallState.PRECISE_CALL_STATE_NOT_VALID
+ && ringingCallState != PreciseCallState.PRECISE_CALL_STATE_IDLE) {
+ CallState.Builder builder = new CallState.Builder(
+ callStates[CallState.CALL_CLASSIFICATION_RINGING])
+ .setNetworkType(mCallNetworkType[phoneId])
+ .setCallQuality(createCallQuality())
+ .setCallClassification(
+ CallState.CALL_CLASSIFICATION_RINGING);
+ if (imsCallIds != null && imsServiceTypes != null && imsCallTypes != null) {
+ builder = builder
+ .setImsCallSessionId(imsCallIds[
+ CallState.CALL_CLASSIFICATION_RINGING])
+ .setImsCallServiceType(imsServiceTypes[
+ CallState.CALL_CLASSIFICATION_RINGING])
+ .setImsCallType(imsCallTypes[
+ CallState.CALL_CLASSIFICATION_RINGING]);
+ }
+ mCallStateLists.get(phoneId).add(builder.build());
+ }
}
for (Record r : mRecords) {
@@ -2213,11 +2288,11 @@
mRemoveList.add(r.binder);
}
}
- if (notifyCallAttributes && r.matchTelephonyCallbackEvent(
+ if (notifyCallState && r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)
&& idMatch(r, subId, phoneId)) {
try {
- r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+ r.callback.onCallStatesChanged(mCallStateLists.get(phoneId));
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2515,15 +2590,29 @@
// merge CallQuality with PreciseCallState and network type
mCallQuality[phoneId] = callQuality;
mCallNetworkType[phoneId] = callNetworkType;
- mCallAttributes[phoneId] = new CallAttributes(mPreciseCallState[phoneId],
- callNetworkType, callQuality);
+ if (mCallStateLists.get(phoneId).size() > 0
+ && mCallStateLists.get(phoneId).get(0).getCallState()
+ == PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
+ CallState prev = mCallStateLists.get(phoneId).remove(0);
+ mCallStateLists.get(phoneId).add(
+ 0, new CallState.Builder(prev.getCallState())
+ .setNetworkType(callNetworkType)
+ .setCallQuality(callQuality)
+ .setCallClassification(prev.getCallClassification())
+ .setImsCallSessionId(prev.getImsCallSessionId())
+ .setImsCallServiceType(prev.getImsCallServiceType())
+ .setImsCallType(prev.getImsCallType()).build());
+ } else {
+ log("There is no active call to report CallQaulity");
+ return;
+ }
for (Record r : mRecords) {
if (r.matchTelephonyCallbackEvent(
TelephonyCallback.EVENT_CALL_ATTRIBUTES_CHANGED)
&& idMatch(r, subId, phoneId)) {
try {
- r.callback.onCallAttributesChanged(mCallAttributes[phoneId]);
+ r.callback.onCallStatesChanged(mCallStateLists.get(phoneId));
} catch (RemoteException ex) {
mRemoveList.add(r.binder);
}
@@ -2991,7 +3080,6 @@
pw.println("mSrvccState=" + mSrvccState[i]);
pw.println("mCallPreciseDisconnectCause=" + mCallPreciseDisconnectCause[i]);
pw.println("mCallQuality=" + mCallQuality[i]);
- pw.println("mCallAttributes=" + mCallAttributes[i]);
pw.println("mCallNetworkType=" + mCallNetworkType[i]);
pw.println("mPreciseDataConnectionStates=" + mPreciseDataConnectionStates.get(i));
pw.println("mOutgoingCallEmergencyNumber=" + mOutgoingCallEmergencyNumber[i]);
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index 86b98f1..2435243 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -5,6 +5,7 @@
import android.net.NetworkCapabilities;
import android.telecom.Connection;
import android.telephony.data.ApnSetting;
+import android.telephony.ims.ImsCallProfile;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -494,7 +495,7 @@
PreciseCallState.PRECISE_CALL_STATE_HOLDING,
PreciseCallState.PRECISE_CALL_STATE_DIALING,
PreciseCallState.PRECISE_CALL_STATE_ALERTING,
- PreciseCallState. PRECISE_CALL_STATE_INCOMING,
+ PreciseCallState.PRECISE_CALL_STATE_INCOMING,
PreciseCallState.PRECISE_CALL_STATE_WAITING,
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTED,
PreciseCallState.PRECISE_CALL_STATE_DISCONNECTING})
@@ -727,6 +728,36 @@
})
public @interface ValidationStatus {}
+ /**
+ * IMS call Service types
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "SERVICE_TYPE_" }, value = {
+ ImsCallProfile.SERVICE_TYPE_NONE,
+ ImsCallProfile.SERVICE_TYPE_NORMAL,
+ ImsCallProfile.SERVICE_TYPE_EMERGENCY,
+ })
+ public @interface ImsCallServiceType {}
+
+ /**
+ * IMS call types
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "CALL_TYPE_" }, value = {
+ ImsCallProfile.CALL_TYPE_NONE,
+ ImsCallProfile.CALL_TYPE_VOICE_N_VIDEO,
+ ImsCallProfile.CALL_TYPE_VOICE,
+ ImsCallProfile.CALL_TYPE_VIDEO_N_VOICE,
+ ImsCallProfile.CALL_TYPE_VT,
+ ImsCallProfile.CALL_TYPE_VT_TX,
+ ImsCallProfile.CALL_TYPE_VT_RX,
+ ImsCallProfile.CALL_TYPE_VT_NODIR,
+ ImsCallProfile.CALL_TYPE_VS,
+ ImsCallProfile.CALL_TYPE_VS_TX,
+ ImsCallProfile.CALL_TYPE_VS_RX,
+ })
+ public @interface ImsCallType {}
+
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = { "NET_CAPABILITY_ENTERPRISE_SUB_LEVEL" }, value = {
diff --git a/telephony/java/android/telephony/CallAttributes.java b/telephony/java/android/telephony/CallAttributes.java
index b7bef39..1dc64a9 100644
--- a/telephony/java/android/telephony/CallAttributes.java
+++ b/telephony/java/android/telephony/CallAttributes.java
@@ -29,8 +29,10 @@
* Contains information about a call's attributes as passed up from the HAL. If there are multiple
* ongoing calls, the CallAttributes will pertain to the call in the foreground.
* @hide
+ * @deprecated use {@link CallState} for call information for each call.
*/
@SystemApi
+@Deprecated
public final class CallAttributes implements Parcelable {
private PreciseCallState mPreciseCallState;
@NetworkType
diff --git a/telephony/java/android/telephony/CallState.aidl b/telephony/java/android/telephony/CallState.aidl
new file mode 100644
index 0000000..dd5af8e
--- /dev/null
+++ b/telephony/java/android/telephony/CallState.aidl
@@ -0,0 +1,20 @@
+/*
+ * 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;
+
+parcelable CallState;
+
diff --git a/telephony/java/android/telephony/CallState.java b/telephony/java/android/telephony/CallState.java
new file mode 100644
index 0000000..51ecfb0
--- /dev/null
+++ b/telephony/java/android/telephony/CallState.java
@@ -0,0 +1,409 @@
+/*
+ * Copyright (C) 2022 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;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.Annotation.ImsCallServiceType;
+import android.telephony.Annotation.ImsCallType;
+import android.telephony.Annotation.NetworkType;
+import android.telephony.Annotation.PreciseCallStates;
+import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.ImsCallSession;
+
+import java.util.Objects;
+
+/**
+ * Contains information about various states for a call.
+ * @hide
+ */
+@SystemApi
+public final class CallState implements Parcelable {
+
+ /**
+ * Call classifications are just used for backward compatibility of deprecated API {@link
+ * TelephonyCallback#CallAttributesListener#onCallAttributesChanged}, Since these will be
+ * removed when the deprecated API is removed, they should not be opened.
+ */
+ /**
+ * Call classification is not valid. It should not be opened.
+ * @hide
+ */
+ public static final int CALL_CLASSIFICATION_UNKNOWN = -1;
+
+ /**
+ * Call classification indicating foreground call
+ * @hide
+ */
+ public static final int CALL_CLASSIFICATION_RINGING = 0;
+
+ /**
+ * Call classification indicating background call
+ * @hide
+ */
+ public static final int CALL_CLASSIFICATION_FOREGROUND = 1;
+
+ /**
+ * Call classification indicating ringing call
+ * @hide
+ */
+ public static final int CALL_CLASSIFICATION_BACKGROUND = 2;
+
+ /**
+ * Call classification Max value.
+ * @hide
+ */
+ public static final int CALL_CLASSIFICATION_MAX = CALL_CLASSIFICATION_BACKGROUND + 1;
+
+ @PreciseCallStates
+ private final int mPreciseCallState;
+
+ @NetworkType
+ private final int mNetworkType; // TelephonyManager.NETWORK_TYPE_* ints
+ private final CallQuality mCallQuality;
+
+ private final int mCallClassification;
+ /**
+ * IMS call session ID. {@link ImsCallSession#getCallId()}
+ */
+ @Nullable
+ private String mImsCallId;
+
+ /**
+ * IMS call service type of this call
+ */
+ @ImsCallServiceType
+ private int mImsCallServiceType;
+
+ /**
+ * IMS call type of this call.
+ */
+ @ImsCallType
+ private int mImsCallType;
+
+ /**
+ * Constructor of CallAttributes
+ *
+ * @param callState call state defined in {@link PreciseCallState}
+ * @param networkType network type for this call attributes
+ * @param callQuality call quality for this call attributes, only CallState in
+ * {@link PreciseCallState#PRECISE_CALL_STATE_ACTIVE} will have valid call
+ * quality.
+ * @param callClassification call classification
+ * @param imsCallId IMS call session ID for this call attributes
+ * @param imsCallServiceType IMS call service type for this call attributes
+ * @param imsCallType IMS call type for this call attributes
+ */
+ private CallState(@PreciseCallStates int callState, @NetworkType int networkType,
+ @NonNull CallQuality callQuality, int callClassification, @Nullable String imsCallId,
+ @ImsCallServiceType int imsCallServiceType, @ImsCallType int imsCallType) {
+ this.mPreciseCallState = callState;
+ this.mNetworkType = networkType;
+ this.mCallQuality = callQuality;
+ this.mCallClassification = callClassification;
+ this.mImsCallId = imsCallId;
+ this.mImsCallServiceType = imsCallServiceType;
+ this.mImsCallType = imsCallType;
+ }
+
+ @NonNull
+ @Override
+ public String toString() {
+ return "mPreciseCallState=" + mPreciseCallState + " mNetworkType=" + mNetworkType
+ + " mCallQuality=" + mCallQuality + " mCallClassification" + mCallClassification
+ + " mImsCallId=" + mImsCallId + " mImsCallServiceType=" + mImsCallServiceType
+ + " mImsCallType=" + mImsCallType;
+ }
+
+ private CallState(Parcel in) {
+ this.mPreciseCallState = in.readInt();
+ this.mNetworkType = in.readInt();
+ this.mCallQuality = in.readParcelable(
+ CallQuality.class.getClassLoader(), CallQuality.class);
+ this.mCallClassification = in.readInt();
+ this.mImsCallId = in.readString();
+ this.mImsCallServiceType = in.readInt();
+ this.mImsCallType = in.readInt();
+ }
+
+ // getters
+ /**
+ * Returns the precise call state of the call.
+ */
+ @PreciseCallStates
+ public int getCallState() {
+ return mPreciseCallState;
+ }
+
+ /**
+ * Returns the {@link TelephonyManager#NetworkType} of the call.
+ *
+ * @see TelephonyManager#NETWORK_TYPE_UNKNOWN
+ * @see TelephonyManager#NETWORK_TYPE_GPRS
+ * @see TelephonyManager#NETWORK_TYPE_EDGE
+ * @see TelephonyManager#NETWORK_TYPE_UMTS
+ * @see TelephonyManager#NETWORK_TYPE_CDMA
+ * @see TelephonyManager#NETWORK_TYPE_EVDO_0
+ * @see TelephonyManager#NETWORK_TYPE_EVDO_A
+ * @see TelephonyManager#NETWORK_TYPE_1xRTT
+ * @see TelephonyManager#NETWORK_TYPE_HSDPA
+ * @see TelephonyManager#NETWORK_TYPE_HSUPA
+ * @see TelephonyManager#NETWORK_TYPE_HSPA
+ * @see TelephonyManager#NETWORK_TYPE_IDEN
+ * @see TelephonyManager#NETWORK_TYPE_EVDO_B
+ * @see TelephonyManager#NETWORK_TYPE_LTE
+ * @see TelephonyManager#NETWORK_TYPE_EHRPD
+ * @see TelephonyManager#NETWORK_TYPE_HSPAP
+ * @see TelephonyManager#NETWORK_TYPE_GSM
+ * @see TelephonyManager#NETWORK_TYPE_TD_SCDMA
+ * @see TelephonyManager#NETWORK_TYPE_IWLAN
+ * @see TelephonyManager#NETWORK_TYPE_LTE_CA
+ * @see TelephonyManager#NETWORK_TYPE_NR
+ */
+ @NetworkType
+ public int getNetworkType() {
+ return mNetworkType;
+ }
+
+ /**
+ * Returns the {#link CallQuality} of the call.
+ * @return call quality for this call attributes, only CallState in {@link
+ * PreciseCallState#PRECISE_CALL_STATE_ACTIVE} will have valid call quality. It will be
+ * null for the call which is not in {@link PreciseCallState#PRECISE_CALL_STATE_ACTIVE}.
+ */
+ @Nullable
+ public CallQuality getCallQuality() {
+ return mCallQuality;
+ }
+
+ /**
+ * Returns the call classification.
+ * @hide
+ */
+ public int getCallClassification() {
+ return mCallClassification;
+ }
+
+ /**
+ * Returns the IMS call session ID.
+ */
+ @Nullable
+ public String getImsCallSessionId() {
+ return mImsCallId;
+ }
+
+ /**
+ * Returns the IMS call service type.
+ */
+ @ImsCallServiceType
+ public int getImsCallServiceType() {
+ return mImsCallServiceType;
+ }
+
+ /**
+ * Returns the IMS call type.
+ */
+ @ImsCallType
+ public int getImsCallType() {
+ return mImsCallType;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mPreciseCallState, mNetworkType, mCallQuality, mCallClassification,
+ mImsCallId, mImsCallServiceType, mImsCallType);
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (o == null || !(o instanceof CallState) || hashCode() != o.hashCode()) {
+ return false;
+ }
+
+ if (this == o) {
+ return true;
+ }
+
+ CallState s = (CallState) o;
+
+ return (mPreciseCallState == s.mPreciseCallState
+ && mNetworkType == s.mNetworkType
+ && Objects.equals(mCallQuality, s.mCallQuality)
+ && mCallClassification == s.mCallClassification
+ && Objects.equals(mImsCallId, s.mImsCallId)
+ && mImsCallType == s.mImsCallType
+ && mImsCallServiceType == s.mImsCallServiceType);
+ }
+
+ /**
+ * {@link Parcelable#describeContents}
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ /**
+ * {@link Parcelable#writeToParcel}
+ */
+ public void writeToParcel(@Nullable Parcel dest, int flags) {
+ dest.writeInt(mPreciseCallState);
+ dest.writeInt(mNetworkType);
+ dest.writeParcelable(mCallQuality, flags);
+ dest.writeInt(mCallClassification);
+ dest.writeString(mImsCallId);
+ dest.writeInt(mImsCallServiceType);
+ dest.writeInt(mImsCallType);
+ }
+
+ public static final @NonNull Creator<CallState> CREATOR = new Creator() {
+ public CallState createFromParcel(Parcel in) {
+ return new CallState(in);
+ }
+
+ public CallState[] newArray(int size) {
+ return new CallState[size];
+ }
+ };
+
+ /**
+ * Builder of {@link CallState}
+ *
+ * <p>The example below shows how you might create a new {@code CallState}:
+ *
+ * <pre><code>
+ *
+ * CallState = new CallState.Builder()
+ * .setCallState(3)
+ * .setNetworkType({@link TelephonyManager#NETWORK_TYPE_LTE})
+ * .setCallQuality({@link CallQuality})
+ * .setImsCallSessionId({@link String})
+ * .setImsCallServiceType({@link ImsCallProfile#SERVICE_TYPE_NORMAL})
+ * .setImsCallType({@link ImsCallProfile#CALL_TYPE_VOICE})
+ * .build();
+ * </code></pre>
+ */
+ public static final class Builder {
+ private @PreciseCallStates int mPreciseCallState;
+ private @NetworkType int mNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ private CallQuality mCallQuality = null;
+ private int mCallClassification = CALL_CLASSIFICATION_UNKNOWN;
+ private String mImsCallId;
+ private @ImsCallServiceType int mImsCallServiceType = ImsCallProfile.SERVICE_TYPE_NONE;
+ private @ImsCallType int mImsCallType = ImsCallProfile.CALL_TYPE_NONE;
+
+
+ /**
+ * Default constructor for the Builder.
+ */
+ public Builder(@PreciseCallStates int preciseCallState) {
+ mPreciseCallState = preciseCallState;
+ }
+
+ /**
+ * Set network type of this call.
+ *
+ * @param networkType the transport type.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public CallState.Builder setNetworkType(@NetworkType int networkType) {
+ this.mNetworkType = networkType;
+ return this;
+ }
+
+ /**
+ * Set the call quality {@link CallQuality} of this call.
+ *
+ * @param callQuality call quality of active call.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public CallState.Builder setCallQuality(@Nullable CallQuality callQuality) {
+ this.mCallQuality = callQuality;
+ return this;
+ }
+
+ /**
+ * Set call classification for this call.
+ *
+ * @param classification call classification type defined in this class.
+ * @return The same instance of the builder.
+ * @hide
+ */
+ @NonNull
+ public CallState.Builder setCallClassification(int classification) {
+ this.mCallClassification = classification;
+ return this;
+ }
+
+ /**
+ * Set IMS call session ID of this call.
+ *
+ * @param imsCallId IMS call session ID.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public CallState.Builder setImsCallSessionId(@Nullable String imsCallId) {
+ this.mImsCallId = imsCallId;
+ return this;
+ }
+
+ /**
+ * Set IMS call service type of this call.
+ *
+ * @param serviceType IMS call service type defined in {@link ImsCallProfile}.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public CallState.Builder setImsCallServiceType(@ImsCallServiceType int serviceType) {
+ this.mImsCallServiceType = serviceType;
+ return this;
+ }
+
+ /**
+ * Set IMS call type of this call.
+ *
+ * @param callType IMS call type defined in {@link ImsCallProfile}.
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public CallState.Builder setImsCallType(@ImsCallType int callType) {
+ this.mImsCallType = callType;
+ return this;
+ }
+
+ /**
+ * Build the {@link CallState}
+ *
+ * @return the {@link CallState} object
+ */
+ @NonNull
+ public CallState build() {
+ return new CallState(
+ mPreciseCallState,
+ mNetworkType,
+ mCallQuality,
+ mCallClassification,
+ mImsCallId,
+ mImsCallServiceType,
+ mImsCallType);
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index e6d7df3..1ea7fdc 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -78,8 +78,9 @@
public static final int SERVICE_TYPE_EMERGENCY = 2;
/**
- * Call types
+ * Call type none
*/
+ public static final int CALL_TYPE_NONE = 0;
/**
* IMSPhone to support IR.92 & IR.94 (voice + video upgrade/downgrade)
*/