diff options
-rw-r--r-- | src/java/com/android/ims/ImsCall.java | 10 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsConnectionStateListener.java | 11 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsManager.java | 10 | ||||
-rw-r--r-- | src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java | 105 | ||||
-rw-r--r-- | src/java/com/android/ims/internal/VideoPauseTracker.java | 9 |
5 files changed, 120 insertions, 25 deletions
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java index 221b4c0d..ad289fd1 100644 --- a/src/java/com/android/ims/ImsCall.java +++ b/src/java/com/android/ims/ImsCall.java @@ -1881,13 +1881,16 @@ public class ImsCall implements ICall { setIsMerged(playDisconnectTone); mSessionEndDuringMerge = true; String reasonInfo; + int reasonCode = ImsReasonInfo.CODE_UNSPECIFIED; if (playDisconnectTone) { + reasonCode = ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE; reasonInfo = "Call ended by network"; } else { + reasonCode = ImsReasonInfo.CODE_LOCAL_ENDED_BY_CONFERENCE_MERGE; reasonInfo = "Call ended during conference merge process."; } mSessionEndDuringMergeReasonInfo = new ImsReasonInfo( - ImsReasonInfo.CODE_UNSPECIFIED, 0, reasonInfo); + reasonCode, 0, reasonInfo); } } @@ -3343,6 +3346,7 @@ public class ImsCall implements ICall { sb.append(" mute:"); sb.append(isMuted() ? "Y" : "N"); if (mCallProfile != null) { + sb.append(" mCallProfile:" + mCallProfile); sb.append(" tech:"); sb.append(mCallProfile.getCallExtra(ImsCallProfile.EXTRA_CALL_RAT_TYPE)); } @@ -3367,8 +3371,12 @@ public class ImsCall implements ICall { sb.append(isConferenceHost() ? "Y" : "N"); sb.append(" buried term:"); sb.append(mSessionEndDuringMerge ? "Y" : "N"); + sb.append(" isVideo: "); + sb.append(isVideoCall() ? "Y" : "N"); sb.append(" wasVideo: "); sb.append(mWasVideoCall ? "Y" : "N"); + sb.append(" isWifi: "); + sb.append(isWifiCall() ? "Y" : "N"); sb.append(" session:"); sb.append(mSession); sb.append(" transientSession:"); diff --git a/src/java/com/android/ims/ImsConnectionStateListener.java b/src/java/com/android/ims/ImsConnectionStateListener.java index f281df1f..4425854b 100644 --- a/src/java/com/android/ims/ImsConnectionStateListener.java +++ b/src/java/com/android/ims/ImsConnectionStateListener.java @@ -27,13 +27,6 @@ import android.net.Uri; */ public class ImsConnectionStateListener { /** - * Called when the device is connected to the IMS network. - */ - public void onImsConnected() { - // no-op - } - - /** * Called when the device is connected to the IMS network with {@param imsRadioTech}. */ public void onImsConnected(int imsRadioTech) { @@ -41,9 +34,9 @@ public class ImsConnectionStateListener { } /** - * Called when the device is trying to connect to the IMS network. + * Called when the device is trying to connect to the IMS network with {@param imsRadioTech}. */ - public void onImsProgressing() { + public void onImsProgressing(int imsRadioTech) { // no-op } diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 7c258291..82f2c68f 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -32,6 +32,7 @@ import android.provider.Settings; import android.telecom.TelecomManager; import android.telephony.CarrierConfigManager; import android.telephony.Rlog; +import android.telephony.ServiceState; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.ims.ImsServiceProxy; @@ -2233,7 +2234,7 @@ public class ImsManager { } if (mListener != null) { - mListener.onImsConnected(); + mListener.onImsConnected(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); } } @@ -2244,7 +2245,7 @@ public class ImsManager { } if (mListener != null) { - mListener.onImsProgressing(); + mListener.onImsProgressing(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); } } @@ -2257,7 +2258,6 @@ public class ImsManager { } if (mListener != null) { - mListener.onImsConnected(); mListener.onImsConnected(imsRadioTech); } } @@ -2271,7 +2271,7 @@ public class ImsManager { } if (mListener != null) { - mListener.onImsProgressing(); + mListener.onImsProgressing(imsRadioTech); } } @@ -2316,7 +2316,7 @@ public class ImsManager { serviceClass + ", event=" + event); if (mListener != null) { - mListener.onImsConnected(); + mListener.onImsConnected(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); } } diff --git a/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java b/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java index fcb9e09b..d6da824f 100644 --- a/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java +++ b/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java @@ -29,6 +29,7 @@ import android.telecom.Log; import android.telecom.VideoProfile; import android.view.Surface; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.os.SomeArgs; import java.util.Collections; @@ -67,6 +68,7 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { private final Set<ImsVideoProviderWrapperCallback> mCallbacks = Collections.newSetFromMap( new ConcurrentHashMap<ImsVideoProviderWrapperCallback, Boolean>(8, 0.9f, 1)); private VideoPauseTracker mVideoPauseTracker = new VideoPauseTracker(); + private boolean mUseVideoPauseWorkaround = false; private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override @@ -207,13 +209,26 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { * * @param VideoProvider */ - public ImsVideoCallProviderWrapper(IImsVideoCallProvider VideoProvider) + public ImsVideoCallProviderWrapper(IImsVideoCallProvider videoProvider) throws RemoteException { - mVideoCallProvider = VideoProvider; - mVideoCallProvider.asBinder().linkToDeath(mDeathRecipient, 0); - mBinder = new ImsVideoCallCallback(); - mVideoCallProvider.setCallback(mBinder); + mVideoCallProvider = videoProvider; + if (videoProvider != null) { + mVideoCallProvider.asBinder().linkToDeath(mDeathRecipient, 0); + + mBinder = new ImsVideoCallCallback(); + mVideoCallProvider.setCallback(mBinder); + } else { + mBinder = null; + } + } + + @VisibleForTesting + public ImsVideoCallProviderWrapper(IImsVideoCallProvider videoProvider, + VideoPauseTracker videoPauseTracker) + throws RemoteException { + this(videoProvider); + mVideoPauseTracker = videoPauseTracker; } /** @inheritDoc */ @@ -323,7 +338,8 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { * @param to The to video state. * @return {@code true} if a pause was requested. */ - private static boolean isPauseRequest(int from, int to) { + @VisibleForTesting + public static boolean isPauseRequest(int from, int to) { boolean fromPaused = VideoProfile.isPaused(from); boolean toPaused = VideoProfile.isPaused(to); @@ -337,7 +353,8 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { * @param to The to video state. * @return {@code true} if a resume was requested. */ - private static boolean isResumeRequest(int from, int to) { + @VisibleForTesting + public static boolean isResumeRequest(int from, int to) { boolean fromPaused = VideoProfile.isPaused(from); boolean toPaused = VideoProfile.isPaused(to); @@ -345,6 +362,30 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { } /** + * Determines if this request includes turning the camera off (ie turning off transmission). + * @param from the from video state. + * @param to the to video state. + * @return true if the state change disables the user's camera. + */ + @VisibleForTesting + public static boolean isTurnOffCameraRequest(int from, int to) { + return VideoProfile.isTransmissionEnabled(from) + && !VideoProfile.isTransmissionEnabled(to); + } + + /** + * Determines if this request includes turning the camera on (ie turning on transmission). + * @param from the from video state. + * @param to the to video state. + * @return true if the state change enables the user's camera. + */ + @VisibleForTesting + public static boolean isTurnOnCameraRequest(int from, int to) { + return !VideoProfile.isTransmissionEnabled(from) + && VideoProfile.isTransmissionEnabled(to); + } + + /** * Filters incoming pause and resume requests based on whether there are other active pause or * resume requests at the current time. * @@ -361,7 +402,8 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { * @return The new toProfile, with the pause bit set or unset based on whether we should * actually pause or resume the video at the current time. */ - private VideoProfile maybeFilterPauseResume(VideoProfile fromProfile, VideoProfile toProfile, + @VisibleForTesting + public VideoProfile maybeFilterPauseResume(VideoProfile fromProfile, VideoProfile toProfile, int source) { int fromVideoState = fromProfile.getVideoState(); int toVideoState = toProfile.getVideoState(); @@ -381,7 +423,9 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { boolean isPauseRequest = isPauseRequest(fromVideoState, toVideoState) || isPauseSpecialCase; boolean isResumeRequest = isResumeRequest(fromVideoState, toVideoState); if (isPauseRequest) { - Log.i(this, "maybeFilterPauseResume: isPauseRequest"); + Log.i(this, "maybeFilterPauseResume: isPauseRequest (from=%s, to=%s)", + VideoProfile.videoStateToString(fromVideoState), + VideoProfile.videoStateToString(toVideoState)); // Check if we have already paused the video in the past. if (!mVideoPauseTracker.shouldPauseVideoFor(source) && !isPauseSpecialCase) { // Note: We don't want to remove the "pause" in the "special case" scenario. If we @@ -393,7 +437,29 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { toProfile = new VideoProfile(toVideoState, toProfile.getQuality()); } } else if (isResumeRequest) { - Log.i(this, "maybeFilterPauseResume: isResumeRequest"); + boolean isTurnOffCameraRequest = isTurnOffCameraRequest(fromVideoState, toVideoState); + boolean isTurnOnCameraRequest = isTurnOnCameraRequest(fromVideoState, toVideoState); + // TODO: Fix vendor code so that this isn't required. + // Some vendors do not properly handle turning the camera on/off when the video is + // in paused state. + // If the request is to turn on/off the camera, it might be in the unfortunate format: + // FROM: Audio Tx Rx Pause TO: Audio Rx + // FROM: Audio Rx Pause TO: Audio Rx Tx + // If this is the case, we should not treat this request as a resume request as well. + // Ideally the IMS stack should treat a turn off camera request as: + // FROM: Audio Tx Rx Pause TO: Audio Rx Pause + // FROM: Audio Rx Pause TO: Audio Rx Tx Pause + // Unfortunately, it does not. ¯\_(ツ)_/¯ + if (mUseVideoPauseWorkaround && (isTurnOffCameraRequest || isTurnOnCameraRequest)) { + Log.i(this, "maybeFilterPauseResume: isResumeRequest, but camera turning on/off so " + + "skipping (from=%s, to=%s)", + VideoProfile.videoStateToString(fromVideoState), + VideoProfile.videoStateToString(toVideoState)); + return toProfile; + } + Log.i(this, "maybeFilterPauseResume: isResumeRequest (from=%s, to=%s)", + VideoProfile.videoStateToString(fromVideoState), + VideoProfile.videoStateToString(toVideoState)); // Check if we should remain paused (other pause requests pending). if (!mVideoPauseTracker.shouldResumeVideoFor(source)) { // There are other pause requests from other sources which are still active, so we @@ -465,4 +531,23 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { public boolean wasVideoPausedFromSource(int source) { return mVideoPauseTracker.wasVideoPausedFromSource(source); } + + public void setUseVideoPauseWorkaround(boolean useVideoPauseWorkaround) { + mUseVideoPauseWorkaround = useVideoPauseWorkaround; + } + + /** + * Called by {@code ImsPhoneConnection} when there is a change to the video state of the call. + * Informs the video pause tracker that the video is no longer paused. This ensures that + * subsequent pause requests are not filtered out. + * + * @param newVideoState The new video state. + */ + public void onVideoStateChanged(int newVideoState) { + if (mVideoPauseTracker.isPaused() && !VideoProfile.isPaused(newVideoState)) { + Log.i(this, "onVideoStateChanged: newVideoState=%s, clearing pending pause requests.", + VideoProfile.videoStateToString(newVideoState)); + mVideoPauseTracker.clearPauseRequests(); + } + } } diff --git a/src/java/com/android/ims/internal/VideoPauseTracker.java b/src/java/com/android/ims/internal/VideoPauseTracker.java index d37f7fa8..a23c5901 100644 --- a/src/java/com/android/ims/internal/VideoPauseTracker.java +++ b/src/java/com/android/ims/internal/VideoPauseTracker.java @@ -150,6 +150,15 @@ public class VideoPauseTracker { } /** + * Clears pending pause requests for the tracker. + */ + public void clearPauseRequests() { + synchronized (mPauseRequestsLock) { + mPauseRequests.clear(); + } + } + + /** * Returns a string equivalent of a {@code SOURCE_*} constant. * * @param source A {@code SOURCE_*} constant. |