From 093382b99ff3d3654dae2d5cca32c076b432a920 Mon Sep 17 00:00:00 2001 From: "James.cf Lin" Date: Thu, 28 Jan 2021 05:53:02 +0800 Subject: [PATCH] [RCS UCE] Do not trigger publish if the RCS capability presence uce is not enabled Bug: 174187744 Test: atest -c CtsTelephonyTestCases:android.telephony.ims.cts.ImsServiceTest Merged-In: Ib3ff6975313e18beb21e7bfcdf6aa0592992eb52 Change-Id: Ib3ff6975313e18beb21e7bfcdf6aa0592992eb52 --- .../com/android/ims/RcsFeatureManager.java | 6 +- .../publish/PublishControllerImpl.java | 66 +++++++++++++++++++ .../presence/publish/PublishProcessor.java | 41 ++++++------ .../publish/PublishControllerImplTest.java | 8 ++- 4 files changed, 99 insertions(+), 22 deletions(-) diff --git a/src/java/com/android/ims/RcsFeatureManager.java b/src/java/com/android/ims/RcsFeatureManager.java index b2faf900..e7980b0c 100644 --- a/src/java/com/android/ims/RcsFeatureManager.java +++ b/src/java/com/android/ims/RcsFeatureManager.java @@ -388,9 +388,13 @@ private static T awaitResult(CountDownLatch latch, AtomicReference result /** * Query the availability of an IMS RCS capability. */ - public boolean isAvailable(@RcsImsCapabilities.RcsImsCapabilityFlag int capability) + public boolean isAvailable(@RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws android.telephony.ims.ImsException { try { + if (mRcsFeatureConnection.getRegistrationTech() != radioTech) { + return false; + } int currentStatus = mRcsFeatureConnection.queryCapabilityStatus(); return new RcsImsCapabilities(currentStatus).isCapable(capability); } catch (RemoteException e) { 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 9003bfd9..4605af27 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 @@ -23,10 +23,13 @@ import android.os.Message; import android.os.RemoteCallbackList; import android.os.RemoteException; +import android.telephony.ims.ImsException; import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.RcsUceAdapter.PublishState; +import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IRcsUcePublishStateCallback; +import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities; import android.util.Log; import com.android.ims.RcsFeatureManager; @@ -68,6 +71,8 @@ DeviceCapabilityListener createDeviceCapListener(Context context, int subId, private final Context mContext; private PublishHandler mPublishHandler; private volatile boolean mIsDestroyedFlag; + private volatile boolean mCapabilityPresenceEnabled; + private volatile RcsFeatureManager mRcsFeatureManager; private final UceControllerCallback mUceCtrlCallback; // The device publish state @@ -94,6 +99,31 @@ DeviceCapabilityListener createDeviceCapListener(Context context, int subId, (context, subId, capInfo, callback, looper) -> new DeviceCapabilityListener(context, subId, capInfo, callback, looper); + // Listen to the RCS availability status changed. + private final IImsCapabilityCallback mRcsCapabilitiesCallback = + new IImsCapabilityCallback.Stub() { + @Override + public void onQueryCapabilityConfiguration( + int resultCapability, int resultRadioTech, boolean enabled) { + } + @Override + public void onCapabilitiesStatusChanged(int capabilities) { + logd("onCapabilitiesStatusChanged: " + capabilities); + RcsImsCapabilities RcsImsCapabilities = new RcsImsCapabilities(capabilities); + mCapabilityPresenceEnabled = + RcsImsCapabilities.isCapable(RcsUceAdapter.CAPABILITY_TYPE_PRESENCE_UCE); + + // Trigger a publish request if the RCS capabilities presence is enabled. + if (mCapabilityPresenceEnabled) { + mPublishProcessor.checkAndSendPendingRequest(); + } + } + @Override + public void onChangeCapabilityConfigurationError(int capability, int radioTech, + int reason) { + } + }; + public PublishControllerImpl(Context context, int subId, UceControllerCallback callback, Looper looper) { mSubId = subId; @@ -142,12 +172,16 @@ private void initDeviceCapabilitiesListener() { @Override public void onRcsConnected(RcsFeatureManager manager) { logd("onRcsConnected"); + mRcsFeatureManager = manager; mPublishProcessor.onRcsConnected(manager); + registerRcsAvailabilityChanged(manager); } @Override public void onRcsDisconnected() { logd("onRcsDisconnected"); + mRcsFeatureManager = null; + mCapabilityPresenceEnabled = false; mPublishProcessor.onRcsDisconnected(); } @@ -155,6 +189,8 @@ public void onRcsDisconnected() { public void onDestroy() { logi("onDestroy"); mIsDestroyedFlag = true; + mCapabilityPresenceEnabled = false; + unregisterRcsAvailabilityChanged(); mDeviceCapListener.onDestroy(); // It will turn off the listener automatically. mPublishHandler.onDestroy(); mPublishProcessor.onDestroy(); @@ -225,6 +261,24 @@ public RcsContactUceCapability getDeviceCapabilities() { return mDeviceCapabilityInfo.getDeviceCapabilities(mContext); } + private void registerRcsAvailabilityChanged(RcsFeatureManager manager) { + try { + manager.registerRcsAvailabilityCallback(mSubId, mRcsCapabilitiesCallback); + } catch (ImsException e) { + logw("registerRcsAvailabilityChanged exception " + e); + } + } + + private void unregisterRcsAvailabilityChanged() { + RcsFeatureManager manager = mRcsFeatureManager; + if (manager == null) return; + try { + manager.unregisterRcsAvailabilityCallback(mSubId, mRcsCapabilitiesCallback); + } catch (Exception e) { + // Do not handle the exception + } + } + // The local publish request from the sub-components which interact with PublishController. private final PublishControllerCallback mPublishControllerCallback = new PublishControllerCallback() { @@ -378,6 +432,13 @@ public void requestPublish(@PublishTriggerType int type, long delay) { if (publishCtrl.mIsDestroyedFlag) return; publishCtrl.logd("requestPublish: " + type + ", delay=" + delay); + // Return if the RCS capabilities presence uce is not enabled. + if (!publishCtrl.mCapabilityPresenceEnabled) { + publishCtrl.logd("requestPublish: Skip. capability presence uce is not enabled."); + publishCtrl.mPublishProcessor.setPendingRequest(true); + return; + } + // Don't send duplicated publish request because it always publish the latest device // capabilities. if (hasMessages(MSG_REQUEST_PUBLISH)) { @@ -520,6 +581,11 @@ public PublishHandler getPublishHandler() { return mPublishHandler; } + @VisibleForTesting + public IImsCapabilityCallback getRcsCapabilitiesCallback() { + return mRcsCapabilitiesCallback; + } + private void logd(String log) { Log.d(LOG_TAG, getLogPrefix().append(log).toString()); } diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishProcessor.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishProcessor.java index 4a197125..6ff0d231 100644 --- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishProcessor.java +++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishProcessor.java @@ -16,6 +16,7 @@ package com.android.ims.rcs.uce.presence.publish; +import android.annotation.NonNull; import android.content.Context; import android.os.RemoteException; import android.telephony.ims.RcsContactUceCapability; @@ -131,8 +132,16 @@ public void doPublish(@PublishTriggerType int triggerType) { return; } + // Set the pending request and return if RCS is not connected. + RcsFeatureManager featureManager = mRcsFeatureManager; + if (featureManager == null) { + logw("doPublish: NOT connected"); + setPendingRequest(true); + return; + } + // Publish to the Presence server. - publishCapabilities(pidfXml); + publishCapabilities(featureManager, pidfXml); } // Check if the giving trigger type should reset the retry count. @@ -169,7 +178,7 @@ private boolean isRequestAllowed() { // Set the pending flag if there's already a request running now. if (mProcessorState.isPublishingNow()) { logd("isPublishAllowed: There is already a request running now"); - mProcessorState.setPendingRequest(true); + setPendingRequest(true); return false; } @@ -186,27 +195,15 @@ private boolean isRequestAllowed() { } // Publish the device capabilities with the given pidf - private void publishCapabilities(String pidfXml) { - if (mIsDestroyed) { - logw("publishCapabilities: This instance is already destroyed"); - return; - } - - // Check if the RCS is connected. - RcsFeatureManager featureManager = mRcsFeatureManager; - if (featureManager == null) { - mLocalLog.log("publish capabilities: not connected"); - logw("publishCapabilities: NOT connected"); - return; - } - + private void publishCapabilities(@NonNull RcsFeatureManager featureManager, + @NonNull String pidfXml) { PublishRequestResponse requestResponse = null; try { // Set publishing flag mProcessorState.setPublishingFlag(true); // Clear the pending request flag since we're publishing the latest device's capability - mProcessorState.setPendingRequest(false); + setPendingRequest(false); // Generate a unique taskId to track this request. long taskId = mProcessorState.generatePublishTaskId(); @@ -251,7 +248,7 @@ public void onCommandError(PublishRequestResponse requestResponse) { mProcessorState.increaseRetryCount(); // Reset the pending flag since it is going to resend a publish request. - mProcessorState.setPendingRequest(false); + setPendingRequest(false); // Resend a publish request long delayTime = mProcessorState.getDelayTimeToAllowPublish(); @@ -292,7 +289,7 @@ public void onNetworkResponse(PublishRequestResponse requestResponse) { mProcessorState.increaseRetryCount(); // Reset the pending flag since it is going to resend a publish request. - mProcessorState.setPendingRequest(false); + setPendingRequest(false); // Resend a publish request long delayTime = mProcessorState.getDelayTimeToAllowPublish(); @@ -369,7 +366,11 @@ private void setRequestEnded(PublishRequestResponse requestResponse) { logd("setRequestEnded: taskId=" + taskId); } - private void checkAndSendPendingRequest() { + public void setPendingRequest(boolean pendingRequest) { + mProcessorState.setPendingRequest(pendingRequest); + } + + public void checkAndSendPendingRequest() { if (mIsDestroyed) return; if (mProcessorState.hasPendingRequest()) { logd("checkAndSendPendingRequest: send pending request"); 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 61a1878b..0c5c056c 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 @@ -21,12 +21,14 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Handler; import android.os.Looper; import android.os.RemoteCallbackList; import android.telephony.ims.RcsUceAdapter; +import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IRcsUcePublishStateCallback; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -159,7 +161,11 @@ public void testRequestPublishFromService() throws Exception { Handler handler = publishController.getPublishHandler(); waitForHandlerAction(handler, 1000); - verify(mPublishProcessor).doPublish(PublishController.PUBLISH_TRIGGER_SERVICE); + verify(mPublishProcessor, never()).doPublish(PublishController.PUBLISH_TRIGGER_SERVICE); + + IImsCapabilityCallback callback = publishController.getRcsCapabilitiesCallback(); + callback.onCapabilitiesStatusChanged(RcsUceAdapter.CAPABILITY_TYPE_PRESENCE_UCE); + verify(mPublishProcessor).checkAndSendPendingRequest(); } private PublishControllerImpl createPublishController() {