aboutsummaryrefslogtreecommitdiff
path: root/src/java/com/android/ims/ImsCall.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/com/android/ims/ImsCall.java')
-rwxr-xr-xsrc/java/com/android/ims/ImsCall.java163
1 files changed, 150 insertions, 13 deletions
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java
index a31971d2..7af0b71c 100755
--- a/src/java/com/android/ims/ImsCall.java
+++ b/src/java/com/android/ims/ImsCall.java
@@ -16,9 +16,11 @@
package com.android.ims;
+import android.annotation.NonNull;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.os.Parcel;
@@ -30,10 +32,12 @@ import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsCallSession;
+import android.telephony.ims.ImsCallSessionListener;
import android.telephony.ims.ImsConferenceState;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsStreamMediaProfile;
import android.telephony.ims.ImsSuppServiceNotification;
+import android.telephony.ims.RtpHeaderExtension;
import android.text.TextUtils;
import android.util.Log;
@@ -46,9 +50,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
-import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@@ -93,11 +95,21 @@ public class ImsCall implements ICall {
*/
public static class Listener {
/**
- * Called when a request is sent out to initiate a new call
- * and 1xx response is received from the network.
+ * Called after the network first begins to establish the call session and is now connecting
+ * to the remote party.
* The default implementation calls {@link #onCallStateChanged}.
- *
- * @param call the call object that carries out the IMS call
+ * <p/>
+ * see: {@link ImsCallSessionListener#callSessionInitiating}
+ */
+ public void onCallInitiating(ImsCall call) {
+ onCallStateChanged(call);
+ }
+
+ /**
+ * Called after the network has contacted the remote party.
+ * The default implementation calls {@link #onCallStateChanged}.
+ * <p/>
+ * see: {@link ImsCallSessionListener#callSessionProgressing}
*/
public void onCallProgressing(ImsCall call) {
onCallStateChanged(call);
@@ -501,6 +513,14 @@ public class ImsCall implements ICall {
}
/**
+ * Reports a DTMF tone received from the network.
+ * @param imsCall The IMS call the tone was received from.
+ * @param digit The digit received.
+ */
+ public void onCallSessionDtmfReceived(ImsCall imsCall, char digit) {
+ }
+
+ /**
* Called when the call quality has changed.
*
* @param imsCall ImsCall object
@@ -508,6 +528,15 @@ public class ImsCall implements ICall {
*/
public void onCallQualityChanged(ImsCall imsCall, CallQuality callQuality) {
}
+
+ /**
+ * Called when RTP header extension data is received from the network.
+ * @param imsCall The ImsCall the data was received on.
+ * @param rtpHeaderExtensionData The RTP extension data received.
+ */
+ public void onCallSessionRtpHeaderExtensionsReceived(ImsCall imsCall,
+ @NonNull Set<RtpHeaderExtension> rtpHeaderExtensionData) {
+ }
}
// List of update operation for IMS call control
@@ -952,7 +981,7 @@ public class ImsCall implements ICall {
*
* @return {@code True} if the call is a multiparty call.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public boolean isMultiparty() {
synchronized(mLockObj) {
if (mSession == null) {
@@ -1217,7 +1246,7 @@ public class ImsCall implements ICall {
* @param number number to be deflected to.
* @throws ImsException if the IMS service fails to deflect the call
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void deflect(String number) throws ImsException {
logi("deflect :: session=" + mSession + ", number=" + Rlog.pii(TAG, number));
@@ -1243,7 +1272,7 @@ public class ImsCall implements ICall {
* @see Listener#onCallStartFailed
* @throws ImsException if the IMS service fails to reject the call
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void reject(int reason) throws ImsException {
logi("reject :: reason=" + reason);
@@ -1328,7 +1357,7 @@ public class ImsCall implements ICall {
*
* @param reason reason code to terminate a call
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public void terminate(int reason) {
logi("terminate :: reason=" + reason);
@@ -1795,6 +1824,30 @@ public class ImsCall implements ICall {
}
}
+ /**
+ * Requests that RTP header extensions are added to the next RTP packet sent by the IMS stack.
+ * <p>
+ * The {@link RtpHeaderExtension#getLocalIdentifier()} local identifiers specified here must match
+ * agreed upon identifiers as indicated in
+ * {@link ImsCallProfile#getAcceptedRtpHeaderExtensionTypes()} for the current
+ * {@link #getCallProfile()}.
+ * <p>
+ * By specification, the RTP header extension is an unacknowledged transmission and there is no
+ * guarantee that the header extension will be delivered by the network to the other end of the
+ * call.
+ * @param rtpHeaderExtensions The RTP header extension(s) to be included in the next RTP
+ * packet.
+ */
+ public void sendRtpHeaderExtensions(@NonNull Set<RtpHeaderExtension> rtpHeaderExtensions) {
+ logi("sendRtpHeaderExtensions; extensionsSent=" + rtpHeaderExtensions.size());
+ synchronized(mLockObj) {
+ if (mSession == null) {
+ loge("sendRtpHeaderExtensions::no session");
+ }
+ mSession.sendRtpHeaderExtensions(rtpHeaderExtensions);
+ }
+ }
+
public void setAnswerWithRtt() {
mAnswerWithRtt = true;
}
@@ -1952,7 +2005,7 @@ public class ImsCall implements ICall {
", status=" + status +
", user=" + Rlog.pii(TAG, user) +
", displayName= " + Rlog.pii(TAG, displayName) +
- ", endpoint=" + endpoint);
+ ", endpoint=" + Rlog.pii(TAG, endpoint));
}
Uri handle = Uri.parse(user);
@@ -2394,6 +2447,32 @@ public class ImsCall implements ICall {
@VisibleForTesting
public class ImsCallSessionListenerProxy extends ImsCallSession.Listener {
@Override
+ public void callSessionInitiating(ImsCallSession session, ImsCallProfile profile) {
+ logi("callSessionInitiating :: session=" + session + " profile=" + profile);
+ if (isTransientConferenceSession(session)) {
+ // If it is a transient (conference) session, there is no action for this signal.
+ logi("callSessionInitiating :: not supported for transient conference session=" +
+ session);
+ return;
+ }
+
+ ImsCall.Listener listener;
+
+ synchronized(ImsCall.this) {
+ listener = mListener;
+ setCallProfile(profile);
+ }
+
+ if (listener != null) {
+ try {
+ listener.onCallInitiating(ImsCall.this);
+ } catch (Throwable t) {
+ loge("callSessionInitiating :: ", t);
+ }
+ }
+ }
+
+ @Override
public void callSessionProgressing(ImsCallSession session, ImsStreamMediaProfile profile) {
logi("callSessionProgressing :: session=" + session + " profile=" + profile);
@@ -2406,8 +2485,14 @@ public class ImsCall implements ICall {
ImsCall.Listener listener;
+ ImsCallProfile updatedProfile = session.getCallProfile();
synchronized(ImsCall.this) {
listener = mListener;
+ // The ImsCallProfile may have updated here (for example call state change). Query
+ // the potentially updated call profile to pick up these changes.
+ setCallProfile(updatedProfile);
+ // Apply the new mediaProfile on top of the Call Profile so it is not ignored in
+ // case the ImsService has not had a chance to update it yet.
mCallProfile.mMediaProfile.copyFrom(profile);
}
@@ -3341,6 +3426,23 @@ public class ImsCall implements ICall {
}
@Override
+ public void callSessionDtmfReceived(char digit) {
+ ImsCall.Listener listener;
+
+ synchronized(ImsCall.this) {
+ listener = mListener;
+ }
+
+ if (listener != null) {
+ try {
+ listener.onCallSessionDtmfReceived(ImsCall.this, digit);
+ } catch (Throwable t) {
+ loge("callSessionDtmfReceived:: ", t);
+ }
+ }
+ }
+
+ @Override
public void callQualityChanged(CallQuality callQuality) {
ImsCall.Listener listener;
@@ -3356,6 +3458,24 @@ public class ImsCall implements ICall {
}
}
}
+
+ @Override
+ public void callSessionRtpHeaderExtensionsReceived(
+ @NonNull Set<RtpHeaderExtension> extensions) {
+ ImsCall.Listener listener;
+
+ synchronized (ImsCall.this) {
+ listener = mListener;
+ }
+
+ if (listener != null) {
+ try {
+ listener.onCallSessionRtpHeaderExtensionsReceived(ImsCall.this, extensions);
+ } catch (Throwable t) {
+ loge("callSessionRtpHeaderExtensionsReceived:: ", t);
+ }
+ }
+ }
}
/**
@@ -3672,8 +3792,7 @@ public class ImsCall implements ICall {
* @param profile The current {@link ImsCallProfile} for the call.
*/
private void trackVideoStateHistory(ImsCallProfile profile) {
- mWasVideoCall = mWasVideoCall
- || profile != null ? profile.isVideoCall() : false;
+ mWasVideoCall = mWasVideoCall || ( profile != null && profile.isVideoCall());
}
/**
@@ -3741,6 +3860,24 @@ public class ImsCall implements ICall {
}
/**
+ * Determines if the current call is a cross sim call
+ * Note: This depends on the RIL exposing the
+ * {@link ImsCallProfile#EXTRA_IS_CROSS_SIM_CALL} extra.
+ *
+ * @return {@code true} if the call is Cross SIM, {@code false} otherwise.
+ */
+ public boolean isCrossSimCall() {
+ synchronized(mLockObj) {
+ if (mCallProfile == null) {
+ return false;
+ }
+ return mCallProfile.getCallExtraBoolean(
+ ImsCallProfile.EXTRA_IS_CROSS_SIM_CALL,
+ false);
+ }
+ }
+
+ /**
* Log a string to the radio buffer at the info level.
* @param s The message to log
*/