diff options
Diffstat (limited to 'src/java/com/android/ims/ImsCall.java')
-rwxr-xr-x | src/java/com/android/ims/ImsCall.java | 163 |
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 */ |