diff options
-rw-r--r-- | src/java/com/android/ims/ImsCall.java | 2 | ||||
-rw-r--r-- | src/java/com/android/ims/ImsManager.java | 208 | ||||
-rw-r--r-- | src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java | 26 | ||||
-rw-r--r-- | src/java/com/android/ims/internal/VideoPauseTracker.java | 8 |
4 files changed, 168 insertions, 76 deletions
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java index ad289fd1..74924e9c 100644 --- a/src/java/com/android/ims/ImsCall.java +++ b/src/java/com/android/ims/ImsCall.java @@ -3238,7 +3238,7 @@ public class ImsCall implements ICall { * * @return {@code true} if a merge into a conference is pending, {@code false} otherwise. */ - private boolean isCallSessionMergePending() { + public boolean isCallSessionMergePending() { return mCallSessionMergePending; } diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java index 82f2c68f..97aa61c5 100644 --- a/src/java/com/android/ims/ImsManager.java +++ b/src/java/com/android/ims/ImsManager.java @@ -200,7 +200,15 @@ public class ImsManager { // Keep track of the ImsRegistrationListenerProxys that have been created so that we can // remove them from the ImsService. - private Set<ImsRegistrationListenerProxy> mRegistrationListeners = new HashSet<>(); + private final Set<ImsConnectionStateListener> mRegistrationListeners = new HashSet<>(); + + private final ImsRegistrationListenerProxy mRegistrationListenerProxy = + new ImsRegistrationListenerProxy(); + + // When true, we have registered the mRegistrationListenerProxy with the ImsService. Don't do + // it again. + private boolean mHasRegisteredForProxy = false; + private final Object mHasRegisteredLock = new Object(); // SystemProperties used as cache private static final String VOLTE_PROVISIONED_PROP = "net.lte.ims.volte.provisioned"; @@ -1509,8 +1517,14 @@ public class ImsManager { int result = 0; try { + // Register a stub implementation of the ImsRegistrationListener. There is the + // possibility that if we use the real implementation of the ImsRegistrationListener, + // it will be added twice. + // TODO: Remove ImsRegistrationListener from startSession API (b/62588776) result = mImsServiceProxy.startSession(incomingCallPendingIntent, - createRegistrationListenerProxy(serviceClass, listener)); + new ImsRegistrationListenerBase()); + addRegistrationListener(listener); + log("open: Session started and registration listener added."); } catch (RemoteException e) { throw new ImsException("open()", e, ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); @@ -1534,23 +1548,45 @@ public class ImsManager { * @param listener To listen to IMS registration events; It cannot be null * @throws NullPointerException if {@code listener} is null * @throws ImsException if calling the IMS service results in an error + * + * @deprecated Use {@link #addRegistrationListener(ImsConnectionStateListener)} instead. */ public void addRegistrationListener(int serviceClass, ImsConnectionStateListener listener) throws ImsException { - checkAndThrowExceptionIfServiceUnavailable(); + addRegistrationListener(listener); + } + + /** + * Adds registration listener to the IMS service. + * + * @param listener To listen to IMS registration events; It cannot be null + * @throws NullPointerException if {@code listener} is null + * @throws ImsException if calling the IMS service results in an error + */ + public void addRegistrationListener(ImsConnectionStateListener listener) + throws ImsException { if (listener == null) { throw new NullPointerException("listener can't be null"); } - - try { - ImsRegistrationListenerProxy p = createRegistrationListenerProxy(serviceClass, - listener); - mRegistrationListeners.add(p); - mImsServiceProxy.addRegistrationListener(p); - } catch (RemoteException e) { - throw new ImsException("addRegistrationListener()", e, - ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + // We only want this Proxy registered once. + synchronized (mHasRegisteredLock) { + if (!mHasRegisteredForProxy) { + try { + checkAndThrowExceptionIfServiceUnavailable(); + mImsServiceProxy.addRegistrationListener(mRegistrationListenerProxy); + log("RegistrationListenerProxy registered."); + // Only record if there isn't a RemoteException. + mHasRegisteredForProxy = true; + } catch (RemoteException e) { + throw new ImsException("addRegistrationListener()", e, + ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + } + } + } + synchronized (mRegistrationListeners) { + log("Local registration listener added: " + listener); + mRegistrationListeners.add(listener); } } @@ -1564,23 +1600,13 @@ public class ImsManager { */ public void removeRegistrationListener(ImsConnectionStateListener listener) throws ImsException { - checkAndThrowExceptionIfServiceUnavailable(); - if (listener == null) { throw new NullPointerException("listener can't be null"); } - try { - Optional<ImsRegistrationListenerProxy> optionalProxy = mRegistrationListeners.stream() - .filter(l -> listener.equals(l.mListener)).findFirst(); - if(optionalProxy.isPresent()) { - ImsRegistrationListenerProxy p = optionalProxy.get(); - mRegistrationListeners.remove(p); - mImsServiceProxy.removeRegistrationListener(p); - } - } catch (RemoteException e) { - throw new ImsException("removeRegistrationListener()", e, - ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN); + synchronized (mRegistrationListeners) { + log("Local registration listener removed: " + listener); + mRegistrationListeners.remove(listener); } } @@ -2036,6 +2062,10 @@ public class ImsManager { Rlog.i(TAG, "Creating ImsService using ImsResolver"); mImsServiceProxy = getServiceProxy(); } + // We have created a new ImsService connection, signal for re-registration + synchronized (mHasRegisteredLock) { + mHasRegisteredForProxy = false; + } } // Deprecated method of binding with the ImsService defined in the ServiceManager. @@ -2093,13 +2123,6 @@ public class ImsManager { } } - private ImsRegistrationListenerProxy createRegistrationListenerProxy(int serviceClass, - ImsConnectionStateListener listener) { - ImsRegistrationListenerProxy proxy = - new ImsRegistrationListenerProxy(serviceClass, listener); - return proxy; - } - private static void log(String s) { Rlog.d(TAG, s); } @@ -2211,30 +2234,76 @@ public class ImsManager { } /** - * Adapter class for {@link IImsRegistrationListener}. + * Stub implementation of the Registration listener that provides no functionality. */ - private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub { - private int mServiceClass; - private ImsConnectionStateListener mListener; + private class ImsRegistrationListenerBase extends IImsRegistrationListener.Stub { - public ImsRegistrationListenerProxy(int serviceClass, - ImsConnectionStateListener listener) { - mServiceClass = serviceClass; - mListener = listener; + @Override + public void registrationConnected() throws RemoteException { } - public boolean isSameProxy(int serviceClass) { - return (mServiceClass == serviceClass); + @Override + public void registrationProgressing() throws RemoteException { } + @Override + public void registrationConnectedWithRadioTech(int imsRadioTech) throws RemoteException { + } + + @Override + public void registrationProgressingWithRadioTech(int imsRadioTech) throws RemoteException { + } + + @Override + public void registrationDisconnected(ImsReasonInfo imsReasonInfo) throws RemoteException { + } + + @Override + public void registrationResumed() throws RemoteException { + } + + @Override + public void registrationSuspended() throws RemoteException { + } + + @Override + public void registrationServiceCapabilityChanged(int serviceClass, int event) + throws RemoteException { + } + + @Override + public void registrationFeatureCapabilityChanged(int serviceClass, int[] enabledFeatures, + int[] disabledFeatures) throws RemoteException { + } + + @Override + public void voiceMessageCountUpdate(int count) throws RemoteException { + } + + @Override + public void registrationAssociatedUriChanged(Uri[] uris) throws RemoteException { + } + + @Override + public void registrationChangeFailed(int targetAccessTech, ImsReasonInfo imsReasonInfo) + throws RemoteException { + } + } + + /** + * Adapter class for {@link IImsRegistrationListener}. + */ + private class ImsRegistrationListenerProxy extends IImsRegistrationListener.Stub { + @Deprecated public void registrationConnected() { if (DBG) { log("registrationConnected ::"); } - if (mListener != null) { - mListener.onImsConnected(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onImsConnected( + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)); } } @@ -2244,8 +2313,9 @@ public class ImsManager { log("registrationProgressing ::"); } - if (mListener != null) { - mListener.onImsProgressing(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onImsProgressing( + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)); } } @@ -2257,8 +2327,8 @@ public class ImsManager { log("registrationConnectedWithRadioTech :: imsRadioTech=" + imsRadioTech); } - if (mListener != null) { - mListener.onImsConnected(imsRadioTech); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onImsConnected(imsRadioTech)); } } @@ -2270,8 +2340,8 @@ public class ImsManager { log("registrationProgressingWithRadioTech :: imsRadioTech=" + imsRadioTech); } - if (mListener != null) { - mListener.onImsProgressing(imsRadioTech); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onImsProgressing(imsRadioTech)); } } @@ -2282,9 +2352,8 @@ public class ImsManager { } addToRecentDisconnectReasons(imsReasonInfo); - - if (mListener != null) { - mListener.onImsDisconnected(imsReasonInfo); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onImsDisconnected(imsReasonInfo)); } } @@ -2294,8 +2363,8 @@ public class ImsManager { log("registrationResumed ::"); } - if (mListener != null) { - mListener.onImsResumed(); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(ImsConnectionStateListener::onImsResumed); } } @@ -2305,8 +2374,8 @@ public class ImsManager { log("registrationSuspended ::"); } - if (mListener != null) { - mListener.onImsSuspended(); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(ImsConnectionStateListener::onImsSuspended); } } @@ -2315,8 +2384,9 @@ public class ImsManager { log("registrationServiceCapabilityChanged :: serviceClass=" + serviceClass + ", event=" + event); - if (mListener != null) { - mListener.onImsConnected(ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onImsConnected( + ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)); } } @@ -2325,9 +2395,10 @@ public class ImsManager { int[] enabledFeatures, int[] disabledFeatures) { log("registrationFeatureCapabilityChanged :: serviceClass=" + serviceClass); - if (mListener != null) { - mListener.onFeatureCapabilityChanged(serviceClass, - enabledFeatures, disabledFeatures); + + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onFeatureCapabilityChanged(serviceClass, + enabledFeatures, disabledFeatures)); } } @@ -2335,8 +2406,8 @@ public class ImsManager { public void voiceMessageCountUpdate(int count) { log("voiceMessageCountUpdate :: count=" + count); - if (mListener != null) { - mListener.onVoiceMessageCountChanged(count); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onVoiceMessageCountChanged(count)); } } @@ -2344,8 +2415,8 @@ public class ImsManager { public void registrationAssociatedUriChanged(Uri[] uris) { if (DBG) log("registrationAssociatedUriChanged ::"); - if (mListener != null) { - mListener.registrationAssociatedUriChanged(uris); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.registrationAssociatedUriChanged(uris)); } } @@ -2354,8 +2425,9 @@ public class ImsManager { if (DBG) log("registrationChangeFailed :: targetAccessTech=" + targetAccessTech + ", imsReasonInfo=" + imsReasonInfo); - if (mListener != null) { - mListener.onRegistrationChangeFailed(targetAccessTech, imsReasonInfo); + synchronized (mRegistrationListeners) { + mRegistrationListeners.forEach(l -> l.onRegistrationChangeFailed(targetAccessTech, + imsReasonInfo)); } } } diff --git a/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java b/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java index d6da824f..ca4078f9 100644 --- a/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java +++ b/src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java @@ -69,6 +69,7 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { new ConcurrentHashMap<ImsVideoProviderWrapperCallback, Boolean>(8, 0.9f, 1)); private VideoPauseTracker mVideoPauseTracker = new VideoPauseTracker(); private boolean mUseVideoPauseWorkaround = false; + private int mCurrentVideoState; private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() { @Override @@ -283,6 +284,16 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { } try { + if (isResumeRequest(fromProfile.getVideoState(), toProfile.getVideoState()) && + !VideoProfile.isPaused(mCurrentVideoState)) { + // Request is to resume, but we're already resumed so ignore the request. + Log.i(this, "onSendSessionModifyRequest: fromVideoState=%s, toVideoState=%s; " + + "skipping resume request - already resumed.", + VideoProfile.videoStateToString(fromProfile.getVideoState()), + VideoProfile.videoStateToString(toProfile.getVideoState())); + return; + } + toProfile = maybeFilterPauseResume(fromProfile, toProfile, VideoPauseTracker.SOURCE_INCALL); @@ -291,9 +302,6 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { Log.i(this, "onSendSessionModifyRequest: fromVideoState=%s, toVideoState=%s; ", VideoProfile.videoStateToString(fromProfile.getVideoState()), VideoProfile.videoStateToString(toProfile.getVideoState())); - if (fromVideoState == toVideoState) { - return; - } mVideoCallProvider.sendSessionModifyRequest(fromProfile, toProfile); } catch (RemoteException e) { } @@ -544,10 +552,18 @@ public class ImsVideoCallProviderWrapper extends Connection.VideoProvider { * @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.", + if (VideoProfile.isPaused(mCurrentVideoState) && !VideoProfile.isPaused(newVideoState)) { + // New video state is un-paused, so clear any pending pause requests. + Log.i(this, "onVideoStateChanged: currentVideoState=%s, newVideoState=%s, " + + "clearing pending pause requests.", + VideoProfile.videoStateToString(mCurrentVideoState), VideoProfile.videoStateToString(newVideoState)); mVideoPauseTracker.clearPauseRequests(); + } else { + Log.d(this, "onVideoStateChanged: currentVideoState=%s, newVideoState=%s", + VideoProfile.videoStateToString(mCurrentVideoState), + VideoProfile.videoStateToString(newVideoState)); } + mCurrentVideoState = newVideoState; } } diff --git a/src/java/com/android/ims/internal/VideoPauseTracker.java b/src/java/com/android/ims/internal/VideoPauseTracker.java index a23c5901..baa3163f 100644 --- a/src/java/com/android/ims/internal/VideoPauseTracker.java +++ b/src/java/com/android/ims/internal/VideoPauseTracker.java @@ -123,8 +123,12 @@ public class VideoPauseTracker { } else { Log.i(this, "shouldResumeVideoFor: source=%s, pendingRequests=%s - not paused", sourceToString(source), sourcesToString(mPauseRequests)); - // Video wasn't paused, so don't resume. - return false; + // Although there are no pending pause requests, it is possible that we cleared the + // pause tracker because the video state reported we're un-paused. In this case it + // is benign to just allow the resume request to be sent since it'll have no effect. + // Re-writing it to squelch the resume would end up causing it to be a pause + // request, which is bad. + return true; } } } |