aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/java/com/android/ims/ImsCall.java2
-rw-r--r--src/java/com/android/ims/ImsManager.java208
-rw-r--r--src/java/com/android/ims/internal/ImsVideoCallProviderWrapper.java26
-rw-r--r--src/java/com/android/ims/internal/VideoPauseTracker.java8
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;
}
}
}