diff options
author | James.cf Lin <jamescflin@google.com> | 2021-06-04 01:41:37 +0800 |
---|---|---|
committer | James.cf Lin <jamescflin@google.com> | 2021-06-04 14:59:34 +0800 |
commit | 4b733da9db01754962d4e4c80040f762352978cb (patch) | |
tree | 6097c27a39388762ca04bddea053f5862f860005 | |
parent | 3808616ef55e642e440f27c90892c11f8e4f4f4b (diff) | |
download | ims-4b733da9db01754962d4e4c80040f762352978cb.tar.gz |
When the capability type is SIP OPTIONS, the PUBLISH STATE should be OK
Bug: 188447963
Test: atest -c CtsTelephonyTestCases:android.telephony.ims.cts.ImsServiceTest
Change-Id: I2c7bb5fe471578e3442c4857b0678fd798a3191e
3 files changed, 150 insertions, 11 deletions
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishControllerImpl.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishControllerImpl.java index 9da4e4f8..e387ca9e 100644 --- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishControllerImpl.java +++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishControllerImpl.java @@ -89,6 +89,8 @@ public class PublishControllerImpl implements PublishController { private volatile RcsFeatureManager mRcsFeatureManager; private final UceControllerCallback mUceCtrlCallback; + // The capability type that the device is using. + private @RcsImsCapabilityFlag int mCapabilityType; // The device publish state private @PublishState int mPublishState; // The timestamp of updating the publish state @@ -154,7 +156,8 @@ public class PublishControllerImpl implements PublishController { } private void initPublishController(Looper looper) { - mPublishState = RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED; + mCapabilityType = PublishUtils.getCapabilityType(mContext, mSubId); + mPublishState = getInitialPublishState(mCapabilityType); mPublishStateCallbacks = new RemoteCallbackList<>(); mPublishHandler = new PublishHandler(this, looper); @@ -166,6 +169,26 @@ public class PublishControllerImpl implements PublishController { // Turn on the listener to listen to the device changes. mDeviceCapListener.initialize(); + + logd("initPublishController completed: capabilityType=" + mCapabilityType + + ", publishState=" + mPublishState); + } + + /** + * Get the initial publish state according to the given capability type. + * <p> + * The default publish state is NOT_PUBLISH when the capability type is PRESENCE. + * The default publish state is OK when the capability type is SIP OPTIONS. + * Otherwise, the default initial value is ERROR. + */ + private int getInitialPublishState(@RcsImsCapabilityFlag int capabilityType) { + if (capabilityType == RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE) { + return RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED; + } else if (capabilityType == RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE) { + return RcsUceAdapter.PUBLISH_STATE_OK; + } else { + return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR; + } } private void initPublishProcessor() { @@ -573,14 +596,7 @@ public class PublishControllerImpl implements PublishController { } public void sendPublishMessage(@PublishTriggerType int type) { - PublishControllerImpl publishCtrl = mPublishControllerRef.get(); - if (publishCtrl == null) return; - if (publishCtrl.mIsDestroyedFlag) return; - - Message message = obtainMessage(); - message.what = MSG_REQUEST_PUBLISH; - message.arg1 = type; - sendMessage(message); + sendPublishMessage(type, 0L); } public void sendPublishMessage(@PublishTriggerType int type, long delay) { @@ -588,6 +604,13 @@ public class PublishControllerImpl implements PublishController { if (publishCtrl == null) return; if (publishCtrl.mIsDestroyedFlag) return; + // Disallow publish if the PRESENCE PUBLISH is not enabled and this request is not + // triggered by the ImsService. + if (!publishCtrl.isPresencePublishEnabled() && type != PUBLISH_TRIGGER_SERVICE) { + publishCtrl.logd("sendPublishMessage: disallowed type=" + type); + return; + } + Message message = obtainMessage(); message.what = MSG_REQUEST_PUBLISH; message.arg1 = type; @@ -692,7 +715,8 @@ public class PublishControllerImpl implements PublishController { // The first PUBLISH request is required to be triggered from the service. if (!mReceivePublishFromService) { - logd("isPublishRequestAllowed: Have not received the first PUBLISH from the service."); + logd("isPublishRequestAllowed: " + + "The first PUBLISH request from the server has not been received."); return false; } @@ -713,6 +737,19 @@ public class PublishControllerImpl implements PublishController { return true; } + /** + * Check whether the PRESENCE PUBLISH should be enabled or not. It should be enabled only when + * the PRESENCE mechanism is supported. + */ + private boolean isPresencePublishEnabled() { + synchronized (mPublishStateLock) { + return mCapabilityType == RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE; + } + } + + /** + * Handle the RCS connected message. This method is called in the handler thread. + */ private void handleRcsConnectedMessage(RcsFeatureManager manager) { if (mIsDestroyedFlag) return; mRcsFeatureManager = manager; @@ -721,15 +758,27 @@ public class PublishControllerImpl implements PublishController { registerRcsAvailabilityChanged(manager); } + /** + * Handle the RCS disconnected message. This method is called in the handler thread. + */ private void handleRcsDisconnectedMessage() { if (mIsDestroyedFlag) return; mRcsFeatureManager = null; - onUnpublish(); mDeviceCapabilityInfo.updatePresenceCapable(false); mDeviceCapListener.onRcsDisconnected(); mPublishProcessor.onRcsDisconnected(); + + // When the RCS is disconnected, update the publish state to NOT_PUBLISH if the PRESENCE + // PUBLISH is enabled. + if (isPresencePublishEnabled()) { + handlePublishStateChangedMessage(RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED, + Instant.now(), null /*pidfXml*/); + } } + /** + * Handle the Destroyed message. This method is called in the handler thread. + */ private void handleDestroyedMessage() { mIsDestroyedFlag = true; mDeviceCapabilityInfo.updatePresenceCapable(false); @@ -768,8 +817,14 @@ public class PublishControllerImpl implements PublishController { } } + /** + * Handle the carrier config changed message. This method is called in the handler thread. + */ private void handleCarrierConfigChangedMessage() { if (mIsDestroyedFlag) return; + + updateCapabilityTypeAndPublishStateIfNeeded(); + String[] newMap = getCarrierServiceDescriptionFeatureTagMap(); if (mDeviceCapabilityInfo.updateCapabilityRegistrationTrackerMap(newMap)) { mPublishHandler.sendPublishMessage( @@ -777,6 +832,37 @@ public class PublishControllerImpl implements PublishController { } } + /** + * Check whether the capability type has changed or not because of the carrier config changed. + * If the capability type has changed, the publish state also needs to be reinitialized. + * <p> + * This method is called in the handler thread. + */ + private void updateCapabilityTypeAndPublishStateIfNeeded() { + synchronized (mPublishStateLock) { + int originalMechanism = mCapabilityType; + mCapabilityType = PublishUtils.getCapabilityType(mContext, mSubId); + + // Return when the capability type has not changed. + if (originalMechanism == mCapabilityType) { + logd("updateCapTypeAndPublishStateIfNeeded: " + + "The capability type is not changed=" + mCapabilityType); + return; + } + + // Reinitialize the publish state because the capability type has changed. + int updatedPublishState = getInitialPublishState(mCapabilityType); + + logd("updateCapTypeAndPublishStateIfNeeded from " + originalMechanism + + " to " + mCapabilityType + ", new publish state=" + updatedPublishState); + + // Update the publish state directly. Because this method is called in the + // handler thread already, the process of updating publish state does not need to be + // sent to the looper again. + handlePublishStateChangedMessage(updatedPublishState, Instant.now(), null /*pidfxml*/); + } + } + private String[] getCarrierServiceDescriptionFeatureTagMap() { CarrierConfigManager manager = mContext.getSystemService(CarrierConfigManager.class); PersistableBundle bundle = manager != null ? manager.getConfigForSubId(mSubId) : @@ -899,6 +985,12 @@ public class PublishControllerImpl implements PublishController { } @VisibleForTesting + public void setCapabilityType(int type) { + mCapabilityType = type; + mPublishState = getInitialPublishState(mCapabilityType); + } + + @VisibleForTesting public void setPublishStateCallback(RemoteCallbackList<IRcsUcePublishStateCallback> list) { mPublishStateCallbacks = list; } diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java index e412cc6d..ea1d11b9 100644 --- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java +++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java @@ -20,6 +20,8 @@ import android.content.Context; import android.net.Uri; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; +import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities; +import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag; import android.text.TextUtils; import android.util.Log; @@ -133,4 +135,17 @@ public class PublishUtils { return telephonyManager.createForSubscriptionId(subId); } } + + static @RcsImsCapabilityFlag int getCapabilityType(Context context, int subId) { + boolean isPresenceSupported = UceUtils.isPresenceSupported(context, subId); + boolean isSipOptionsSupported = UceUtils.isSipOptionsSupported(context, subId); + if (isPresenceSupported) { + return RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE; + } else if (isSipOptionsSupported) { + return RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE; + } else { + // Return NONE when neither OPTIONS nor PRESENCE is supported. + return RcsImsCapabilities.CAPABILITY_TYPE_NONE; + } + } } diff --git a/tests/src/com/android/ims/rcs/uce/presence/publish/PublishControllerImplTest.java b/tests/src/com/android/ims/rcs/uce/presence/publish/PublishControllerImplTest.java index ba388104..b4c9b873 100644 --- a/tests/src/com/android/ims/rcs/uce/presence/publish/PublishControllerImplTest.java +++ b/tests/src/com/android/ims/rcs/uce/presence/publish/PublishControllerImplTest.java @@ -35,6 +35,7 @@ import android.os.RemoteCallbackList; import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IRcsUcePublishStateCallback; +import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.filters.SmallTest; @@ -315,11 +316,42 @@ public class PublishControllerImplTest extends ImsTestBase { assertFalse("still contained 555-555-1212: " + testString, result.contains("555-555-1212")); } + @Test + @SmallTest + public void testNotPublishWhitSipOptions() throws Exception { + PublishControllerImpl publishController = createPublishController(); + publishController.setCapabilityType(RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE); + doReturn(Optional.of(0L)).when(mPublishProcessor).getPublishingDelayTime(); + + // Trigger a publish request (VT changes) + PublishControllerCallback callback = publishController.getPublishControllerCallback(); + callback.requestPublishFromInternal(PUBLISH_TRIGGER_VT_SETTING_CHANGE); + Handler handler = publishController.getPublishHandler(); + waitForHandlerAction(handler, 1000); + + // Verify it cannot be processed because the capability type is SIP OPTIONS and the publish + // request is triggered from device changed + verify(mPublishProcessor, never()).doPublish(PUBLISH_TRIGGER_VT_SETTING_CHANGE); + + // Set the PRESENCE is capable + IImsCapabilityCallback RcsCapCallback = publishController.getRcsCapabilitiesCallback(); + RcsCapCallback.onCapabilitiesStatusChanged(RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE); + + // Trigger the PUBLISH request from the service. + publishController.requestPublishCapabilitiesFromService( + RcsUceAdapter.CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN); + waitForHandlerAction(handler, 1000); + + // Verify the request which is from the service can be processed + verify(mPublishProcessor).doPublish(PublishController.PUBLISH_TRIGGER_SERVICE); + } + private PublishControllerImpl createPublishController() { PublishControllerImpl publishController = new PublishControllerImpl(mContext, mSubId, mUceCtrlCallback, Looper.getMainLooper(), mDeviceCapListenerFactory, mPublishProcessorFactory); publishController.setPublishStateCallback(mPublishStateCallbacks); + publishController.setCapabilityType(RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE); return publishController; } } |