aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:17:20 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-07-07 05:17:20 +0000
commit9ce6c9c87023dabbe81b19b53de58bafb404513d (patch)
tree52933cf2b7713a4c25d0fd324994920974372bf7
parent16a3207502074e1663988227f8d55e25fe7b7bb4 (diff)
parentf61dbc79584e2bd99c6588abed0d176b368a20d5 (diff)
downloadims-android14-mainline-sdkext-release.tar.gz
Snap for 10453563 from f61dbc79584e2bd99c6588abed0d176b368a20d5 to mainline-sdkext-releaseaml_sdk_341510000aml_sdk_341410000aml_sdk_341110080aml_sdk_341110000aml_sdk_341010000aml_sdk_340912010android14-mainline-sdkext-release
Change-Id: I2c945812f5cccba6ec3ad7176a6831bccb085a22
-rw-r--r--OWNERS7
-rwxr-xr-xsrc/java/com/android/ims/ImsCall.java55
-rw-r--r--src/java/com/android/ims/ImsManager.java163
-rw-r--r--src/java/com/android/ims/ImsUt.java4
-rw-r--r--src/java/com/android/ims/MmTelFeatureConnection.java92
-rw-r--r--src/java/com/android/ims/RcsFeatureManager.java43
-rw-r--r--src/java/com/android/ims/rcs/uce/UceController.java55
-rw-r--r--src/java/com/android/ims/rcs/uce/eab/EabBulkCapabilityUpdater.java5
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java105
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListener.java56
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/PublishController.java39
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/PublishControllerImpl.java89
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/PublishProcessor.java26
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/PublishRequestResponse.java80
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTracker.java10
-rw-r--r--src/java/com/android/ims/rcs/uce/presence/publish/ServiceDescription.java14
-rw-r--r--src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java34
-rw-r--r--src/java/com/android/ims/rcs/uce/request/OptionsRequestCoordinator.java4
-rw-r--r--src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java32
-rw-r--r--src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java43
-rw-r--r--src/java/com/android/ims/rcs/uce/request/UceRequestCoordinator.java51
-rw-r--r--src/java/com/android/ims/rcs/uce/request/UceRequestManager.java8
-rw-r--r--src/java/com/android/ims/rcs/uce/util/FeatureTags.java12
-rw-r--r--tests/Android.bp5
-rw-r--r--tests/src/com/android/ims/ContextFixture.java13
-rw-r--r--tests/src/com/android/ims/ImsManagerTest.java10
-rw-r--r--tests/src/com/android/ims/rcs/uce/UceControllerTest.java8
-rw-r--r--tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java128
-rw-r--r--tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListenerTest.java83
-rw-r--r--tests/src/com/android/ims/rcs/uce/presence/publish/PublishControllerImplTest.java65
-rw-r--r--tests/src/com/android/ims/rcs/uce/presence/publish/PublishProcessorTest.java33
-rw-r--r--tests/src/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTrackerTest.java25
-rw-r--r--tests/src/com/android/ims/rcs/uce/request/SubscribeCoordinatorTest.java58
-rw-r--r--tests/src/com/android/ims/rcs/uce/request/SubscribeRequestTest.java27
-rw-r--r--tests/src/com/android/ims/rcs/uce/request/UceRequestManagerTest.java9
35 files changed, 1130 insertions, 361 deletions
diff --git a/OWNERS b/OWNERS
index 8a0d4eda..fa4ba423 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,4 +1,7 @@
breadley@google.com
-hallliu@google.com
tgunn@google.com
-dbright@google.com
+chinmayd@google.com
+xiaotonj@google.com
+tjstuart@google.com
+grantmenke@google.com
+pmadapurmath@google.com
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java
index 06230a16..29f6acd4 100755
--- a/src/java/com/android/ims/ImsCall.java
+++ b/src/java/com/android/ims/ImsCall.java
@@ -537,6 +537,22 @@ public class ImsCall implements ICall {
public void onCallSessionRtpHeaderExtensionsReceived(ImsCall imsCall,
@NonNull Set<RtpHeaderExtension> rtpHeaderExtensionData) {
}
+
+ /**
+ * Access Network Bitrate Recommendation Query (ANBRQ), see 3GPP TS 26.114.
+ * This API triggers radio to send ANBRQ message to the access network to query the
+ * desired bitrate.
+ *
+ * @param imsCall The ImsCall the data was received on.
+ * @param mediaType MediaType is used to identify media stream such as audio or video.
+ * @param direction Direction of this packet stream (e.g. uplink or downlink).
+ * @param bitsPerSecond This value is the bitrate requested by the other party UE through
+ * RTP CMR, RTCPAPP or TMMBR, and ImsStack converts this value to the MAC bitrate
+ * (defined in TS36.321, range: 0 ~ 8000 kbit/s).
+ */
+ public void onCallSessionSendAnbrQuery(ImsCall imsCall, int mediaType, int direction,
+ int bitsPerSecond) {
+ }
}
// List of update operation for IMS call control
@@ -886,11 +902,25 @@ public class ImsCall implements ICall {
}
/**
- * Gets the specified property of this call.
+ * Deliver the bitrate for the indicated media type, direction and bitrate to the upper layer.
*
- * @param name key to get the extra call information defined in {@link ImsCallProfile}
- * @return the extra call information as string
+ * @param mediaType MediaType is used to identify media stream such as audio or video.
+ * @param direction Direction of this packet stream (e.g. uplink or downlink).
+ * @param bitsPerSecond This value is the bitrate received from the NW through the Recommended
+ * bitrate MAC Control Element message and ImsStack converts this value from MAC bitrate
+ * to audio/video codec bitrate (defined in TS26.114).
+ * @hide
*/
+ public void callSessionNotifyAnbr(int mediaType, int direction, int bitsPerSecond) {
+ synchronized(mLockObj) {
+ if (mSession != null) {
+ mSession.callSessionNotifyAnbr(mediaType, direction, bitsPerSecond);
+ } else {
+ logi("callSessionNotifyAnbr : session - null");
+ }
+ }
+ }
+
public String getCallExtra(String name) throws ImsException {
// Lookup the cache
@@ -3491,6 +3521,25 @@ public class ImsCall implements ICall {
}
}
}
+
+ @Override
+ public void callSessionSendAnbrQuery(int mediaType, int direction, int bitsPerSecond) {
+ ImsCall.Listener listener;
+
+ logi("callSessionSendAnbrQuery in ImsCall");
+ synchronized (ImsCall.this) {
+ listener = mListener;
+ }
+
+ if (listener != null) {
+ try {
+ listener.onCallSessionSendAnbrQuery(ImsCall.this, mediaType,
+ direction, bitsPerSecond);
+ } catch (Throwable t) {
+ loge("callSessionSendAnbrQuery:: ", t);
+ }
+ }
+ }
}
/**
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
index c41426d0..b5a1168b 100644
--- a/src/java/com/android/ims/ImsManager.java
+++ b/src/java/com/android/ims/ImsManager.java
@@ -49,9 +49,12 @@ import android.telephony.ims.ImsCallSession;
import android.telephony.ims.ImsMmTelManager;
import android.telephony.ims.ImsReasonInfo;
import android.telephony.ims.ImsService;
+import android.telephony.ims.MediaQualityStatus;
+import android.telephony.ims.MediaThreshold;
import android.telephony.ims.ProvisioningManager;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.RtpHeaderExtensionType;
+import android.telephony.ims.SrvccCall;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
import android.telephony.ims.aidl.IImsConfigCallback;
@@ -60,6 +63,7 @@ import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IImsSmsListener;
import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.aidl.ISrvccStartedCallback;
import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.MmTelFeature;
@@ -257,7 +261,7 @@ public class ImsManager implements FeatureUpdates {
@VisibleForTesting
public interface SubscriptionManagerProxy {
boolean isValidSubscriptionId(int subId);
- int[] getSubscriptionIds(int slotIndex);
+ int getSubscriptionId(int slotIndex);
int getDefaultVoicePhoneId();
int getIntegerSubscriptionProperty(int subId, String propKey, int defValue);
void setSubscriptionProperty(int subId, String propKey, String propValue);
@@ -292,8 +296,8 @@ public class ImsManager implements FeatureUpdates {
}
@Override
- public int[] getSubscriptionIds(int slotIndex) {
- return getSubscriptionManager().getSubscriptionIds(slotIndex);
+ public int getSubscriptionId(int slotIndex) {
+ return SubscriptionManager.getSubscriptionId(slotIndex);
}
@Override
@@ -1433,12 +1437,7 @@ public class ImsManager implements FeatureUpdates {
}
private int getSubId() {
- int[] subIds = mSubscriptionManagerProxy.getSubscriptionIds(mPhoneId);
- int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- if (subIds != null && subIds.length >= 1) {
- subId = subIds[0];
- }
- return subId;
+ return mSubscriptionManagerProxy.getSubscriptionId(mPhoneId);
}
private void setWfcModeInternal(int wfcMode) {
@@ -2689,11 +2688,139 @@ public class ImsManager implements FeatureUpdates {
}
}
+ /**
+ * Notifies the change of user setting.
+ *
+ * @param enabled indicates whether the user setting for call waiting is enabled or not.
+ */
+ public void setTerminalBasedCallWaitingStatus(boolean enabled) throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.setTerminalBasedCallWaitingStatus(enabled);
+ } catch (ServiceSpecificException se) {
+ if (se.errorCode
+ == android.telephony.ims.ImsException.CODE_ERROR_UNSUPPORTED_OPERATION) {
+ throw new ImsException("setTerminalBasedCallWaitingStatus()", se,
+ ImsReasonInfo.CODE_LOCAL_IMS_NOT_SUPPORTED_ON_DEVICE);
+ } else {
+ throw new ImsException("setTerminalBasedCallWaitingStatus()", se,
+ ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+ }
+ } catch (RemoteException e) {
+ throw new ImsException("setTerminalBasedCallWaitingStatus()", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Returns whether all of the capabilities specified are capable or not.
+ */
+ public boolean isCapable(@ImsService.ImsServiceCapability long capabilities)
+ throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ return c.isCapable(capabilities);
+ } catch (RemoteException e) {
+ throw new ImsException("isCapable()", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Notifies SRVCC started.
+ * @param cb The callback to receive the list of {@link SrvccCall}.
+ */
+ public void notifySrvccStarted(ISrvccStartedCallback cb)
+ throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.notifySrvccStarted(cb);
+ } catch (RemoteException e) {
+ throw new ImsException("notifySrvccStarted", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Notifies SRVCC is completed, IMS service will hang up all calls.
+ */
+ public void notifySrvccCompleted() throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.notifySrvccCompleted();
+ } catch (RemoteException e) {
+ throw new ImsException("notifySrvccCompleted", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Notifies SRVCC failed. IMS service will recover and continue calls over IMS.
+ */
+ public void notifySrvccFailed() throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.notifySrvccFailed();
+ } catch (RemoteException e) {
+ throw new ImsException("notifySrvccFailed", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Notifies SRVCC is canceled. IMS service will recover and continue calls over IMS.
+ */
+ public void notifySrvccCanceled() throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.notifySrvccCanceled();
+ } catch (RemoteException e) {
+ throw new ImsException("notifySrvccCanceled", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
+ /**
+ * Notifies that radio triggered IMS deregistration.
+ * @param reason the reason why the deregistration is triggered.
+ */
+ public void triggerDeregistration(@ImsRegistrationImplBase.ImsDeregistrationReason int reason)
+ throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.triggerDeregistration(reason);
+ } catch (RemoteException e) {
+ throw new ImsException("triggerDeregistration", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
public int getImsServiceState() throws ImsException {
MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
return c.getFeatureState();
}
+ public void setMediaThreshold(@MediaQualityStatus.MediaSessionType int sessionType,
+ MediaThreshold threshold) throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ c.setMediaThreshold(sessionType, threshold);
+ } catch (RemoteException e) {
+ loge("setMediaThreshold Failed.");
+ }
+ }
+
+ public MediaQualityStatus queryMediaQualityStatus (
+ @MediaQualityStatus.MediaSessionType int sessionType) throws ImsException {
+ MmTelFeatureConnection c = getOrThrowExceptionIfServiceUnavailable();
+ try {
+ return c.queryMediaQualityStatus(sessionType);
+ } catch (RemoteException e) {
+ loge("queryMediaQualityStatus Failed.");
+ return null;
+ }
+ }
+
@Override
public void updateFeatureState(int state) {
mMmTelConnectionRef.get().updateFeatureState(state);
@@ -2975,6 +3102,15 @@ public class ImsManager implements FeatureUpdates {
}
}
+ public void onMemoryAvailable(int token) throws ImsException {
+ try {
+ mMmTelConnectionRef.get().onMemoryAvailable(token);
+ } catch (RemoteException e) {
+ throw new ImsException("onMemoryAvailable()", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
public void acknowledgeSms(int token, int messageRef, int result) throws ImsException {
try {
mMmTelConnectionRef.get().acknowledgeSms(token, messageRef, result);
@@ -2984,6 +3120,15 @@ public class ImsManager implements FeatureUpdates {
}
}
+ public void acknowledgeSms(int token, int messageRef, int result, byte[] pdu) throws ImsException {
+ try {
+ mMmTelConnectionRef.get().acknowledgeSms(token, messageRef, result, pdu);
+ } catch (RemoteException e) {
+ throw new ImsException("acknowledgeSms()", e,
+ ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+ }
+ }
+
public void acknowledgeSmsReport(int token, int messageRef, int result) throws ImsException{
try {
mMmTelConnectionRef.get().acknowledgeSmsReport(token, messageRef, result);
diff --git a/src/java/com/android/ims/ImsUt.java b/src/java/com/android/ims/ImsUt.java
index d02ffaa5..17e34154 100644
--- a/src/java/com/android/ims/ImsUt.java
+++ b/src/java/com/android/ims/ImsUt.java
@@ -382,9 +382,9 @@ public class ImsUt implements ImsUtInterface {
String[] barrList, int serviceClass, String password) {
if (DBG) {
if (barrList != null) {
- String bList = new String();
+ String bList = "";
for (int i = 0; i < barrList.length; i++) {
- bList.concat(barrList[i] + " ");
+ bList += barrList[i] + " ";
}
log("updateCallBarring :: Ut=" + miUt + ", cbType=" + cbType
+ ", action=" + action + ", serviceClass=" + serviceClass
diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java
index 3170d413..c09fd94f 100644
--- a/src/java/com/android/ims/MmTelFeatureConnection.java
+++ b/src/java/com/android/ims/MmTelFeatureConnection.java
@@ -22,8 +22,11 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.Message;
import android.os.RemoteException;
+import android.telephony.SubscriptionManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsService;
+import android.telephony.ims.MediaQualityStatus;
+import android.telephony.ims.MediaThreshold;
import android.telephony.ims.RtpHeaderExtensionType;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
@@ -33,11 +36,14 @@ import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.telephony.ims.aidl.IImsSmsListener;
import android.telephony.ims.aidl.ISipTransport;
+import android.telephony.ims.aidl.ISrvccStartedCallback;
import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.MmTelFeature;
import android.telephony.ims.stub.ImsEcbmImplBase;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsSmsImplBase;
import android.util.Log;
+import android.util.SparseArray;
import com.android.ims.internal.IImsCallSession;
import com.android.ims.internal.IImsEcbm;
@@ -45,7 +51,7 @@ import com.android.ims.internal.IImsMultiEndpoint;
import com.android.ims.internal.IImsUt;
import java.util.ArrayList;
-import java.util.Optional;
+import java.util.HashMap;
import java.util.Set;
/**
@@ -100,7 +106,6 @@ public class MmTelFeatureConnection extends FeatureConnection {
}
private class CapabilityCallbackManager extends ImsCallbackAdapterManager<IImsCapabilityCallback> {
-
public CapabilityCallbackManager(Context context, Object lock) {
super(context, lock, mSlotId, mSubId);
}
@@ -376,6 +381,22 @@ public class MmTelFeatureConnection extends FeatureConnection {
mProvisioningCallbackManager.removeCallback(callback);
}
+ public void setMediaThreshold(@MediaQualityStatus.MediaSessionType int sessionType,
+ MediaThreshold threshold) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).setMediaQualityThreshold(sessionType, threshold);
+ }
+ }
+
+ public MediaQualityStatus queryMediaQualityStatus(
+ @MediaQualityStatus.MediaSessionType int sessionType) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ return getServiceInterface(mBinder).queryMediaQualityStatus(sessionType);
+ }
+ }
+
public void changeEnabledCapabilities(CapabilityChangeRequest request,
IImsCapabilityCallback callback) throws RemoteException {
synchronized (mLock) {
@@ -504,6 +525,13 @@ public class MmTelFeatureConnection extends FeatureConnection {
}
}
+ public void onMemoryAvailable(int token) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).onMemoryAvailable(token);
+ }
+ }
+
public void acknowledgeSms(int token, int messageRef,
@ImsSmsImplBase.SendStatusResult int result) throws RemoteException {
synchronized (mLock) {
@@ -512,6 +540,14 @@ public class MmTelFeatureConnection extends FeatureConnection {
}
}
+ public void acknowledgeSms(int token, int messageRef,
+ @ImsSmsImplBase.SendStatusResult int result, byte[] pdu) throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).acknowledgeSmsWithPdu(token, messageRef, result, pdu);
+ }
+ }
+
public void acknowledgeSmsReport(int token, int messageRef,
@ImsSmsImplBase.StatusReportResult int result) throws RemoteException {
synchronized (mLock) {
@@ -541,6 +577,45 @@ public class MmTelFeatureConnection extends FeatureConnection {
}
}
+ public void notifySrvccStarted(ISrvccStartedCallback cb)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).notifySrvccStarted(cb);
+ }
+ }
+
+ public void notifySrvccCompleted() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).notifySrvccCompleted();
+ }
+ }
+
+ public void notifySrvccFailed() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).notifySrvccFailed();
+ }
+ }
+
+ public void notifySrvccCanceled() throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).notifySrvccCanceled();
+ }
+ }
+
+ public void triggerDeregistration(@ImsRegistrationImplBase.ImsDeregistrationReason int reason)
+ throws RemoteException {
+ IImsRegistration registration = getRegistration();
+ if (registration != null) {
+ registration.triggerDeregistration(reason);
+ } else {
+ Log.e(TAG + " [" + mSlotId + "]", "triggerDeregistration IImsRegistration is null");
+ }
+ }
+
public @MmTelFeature.ProcessCallResult int shouldProcessCall(boolean isEmergency,
String[] numbers) throws RemoteException {
if (isEmergency && !isEmergencyMmTelAvailable()) {
@@ -576,6 +651,19 @@ public class MmTelFeatureConnection extends FeatureConnection {
}
}
+ /**
+ * Notifies the MmTelFeature of the enablement status of terminal based call waiting
+ *
+ * @param enabled indicates whether the user setting for call waiting is enabled or not.
+ */
+ public void setTerminalBasedCallWaitingStatus(boolean enabled)
+ throws RemoteException {
+ synchronized (mLock) {
+ checkServiceIsReady();
+ getServiceInterface(mBinder).setTerminalBasedCallWaitingStatus(enabled);
+ }
+ }
+
private IImsMmTelFeature getServiceInterface(IBinder b) {
return IImsMmTelFeature.Stub.asInterface(b);
}
diff --git a/src/java/com/android/ims/RcsFeatureManager.java b/src/java/com/android/ims/RcsFeatureManager.java
index e034a68d..e3f50c34 100644
--- a/src/java/com/android/ims/RcsFeatureManager.java
+++ b/src/java/com/android/ims/RcsFeatureManager.java
@@ -16,6 +16,8 @@
package com.android.ims;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.net.Uri;
import android.os.IBinder;
@@ -30,6 +32,7 @@ import android.telephony.ims.ImsException;
import android.telephony.ims.ImsService;
import android.telephony.ims.RcsUceAdapter.StackPublishTriggerType;
import android.telephony.ims.RegistrationManager;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsConfig;
@@ -44,7 +47,6 @@ import android.telephony.ims.aidl.ISipTransport;
import android.telephony.ims.aidl.ISubscribeResponseCallback;
import android.telephony.ims.feature.CapabilityChangeRequest;
import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.feature.RcsFeature;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.util.Log;
@@ -96,8 +98,7 @@ public class RcsFeatureManager implements FeatureUpdates {
* This method must be called to notify the framework of SUCCESS (200 OK) and FAILURE (300+)
* codes in order to keep the AOSP stack up to date.
*/
- void onPublishUpdated(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText);
+ void onPublishUpdated(SipDetails details);
/**
* Receive a capabilities request from the remote client.
@@ -123,10 +124,9 @@ public class RcsFeatureManager implements FeatureUpdates {
}
@Override
- public void onPublishUpdated(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
- mCapabilityEventCallback.forEach(callback -> callback.onPublishUpdated(
- reasonCode, reasonPhrase, reasonHeaderCause, reasonHeaderText));
+ public void onPublishUpdated(@NonNull SipDetails details) {
+ mCapabilityEventCallback.forEach(
+ callback ->callback.onPublishUpdated(details));
}
@Override
@@ -604,38 +604,15 @@ public class RcsFeatureManager implements FeatureUpdates {
mRcsFeatureConnection.updateFeatureCapabilities(capabilities);
}
- /**
- * Testing interface used to mock SubscriptionManager in testing
- * @hide
- */
- @VisibleForTesting
- public interface SubscriptionManagerProxy {
- /**
- * Mock-able interface for {@link SubscriptionManager#getSubId(int)} used for testing.
- */
- int getSubId(int slotId);
- }
-
public IImsConfig getConfig() {
return mRcsFeatureConnection.getConfig();
}
- private static SubscriptionManagerProxy sSubscriptionManagerProxy
- = slotId -> {
- int[] subIds = SubscriptionManager.getSubId(slotId);
- if (subIds != null) {
- return subIds[0];
- }
- return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
- };
-
/**
- * Testing function used to mock SubscriptionManager in testing
- * @hide
+ * @return the subscription ID associated with this ImsService connection.
*/
- @VisibleForTesting
- public static void setSubscriptionManager(SubscriptionManagerProxy proxy) {
- sSubscriptionManagerProxy = proxy;
+ public int getSubId() {
+ return mRcsFeatureConnection.getSubId();
}
private void log(String s) {
diff --git a/src/java/com/android/ims/rcs/uce/UceController.java b/src/java/com/android/ims/rcs/uce/UceController.java
index 6fb27b06..aeab0611 100644
--- a/src/java/com/android/ims/rcs/uce/UceController.java
+++ b/src/java/com/android/ims/rcs/uce/UceController.java
@@ -18,6 +18,7 @@ package com.android.ims.rcs.uce;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.net.Uri;
import android.os.HandlerThread;
@@ -28,6 +29,7 @@ import android.telephony.ims.RcsContactUceCapability.CapabilityMechanism;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.RcsUceAdapter.PublishState;
import android.telephony.ims.RcsUceAdapter.StackPublishTriggerType;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IOptionsRequestCallback;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
@@ -212,7 +214,7 @@ public class UceController {
private static class CachedCapabilityEvent {
private Optional<Integer> mRequestPublishCapabilitiesEvent;
private Optional<Boolean> mUnpublishEvent;
- private Optional<SomeArgs> mPublishUpdatedEvent;
+ private Optional<SipDetails> mPublishUpdatedEvent;
private Optional<SomeArgs> mRemoteCapabilityRequestEvent;
public CachedCapabilityEvent() {
@@ -239,14 +241,8 @@ public class UceController {
/**
* Cache the publish update event triggered by the ImsService.
*/
- public synchronized void setOnPublishUpdatedEvent(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = reasonCode;
- args.arg2 = reasonPhrase;
- args.arg3 = reasonHeaderCause;
- args.arg4 = reasonHeaderText;
- mPublishUpdatedEvent = Optional.of(args);
+ public synchronized void setOnPublishUpdatedEvent(SipDetails details) {
+ mPublishUpdatedEvent = Optional.of(details);
}
/**
@@ -272,7 +268,7 @@ public class UceController {
}
/** @Return the cached pubilsh update event */
- public synchronized Optional<SomeArgs> getPublishUpdatedEvent() {
+ public synchronized Optional<SipDetails> getPublishUpdatedEvent() {
return mPublishUpdatedEvent;
}
@@ -285,7 +281,6 @@ public class UceController {
public synchronized void clear() {
mRequestPublishCapabilitiesEvent = Optional.empty();
mUnpublishEvent = Optional.empty();
- mPublishUpdatedEvent.ifPresent(args -> args.recycle());
mPublishUpdatedEvent = Optional.empty();
mRemoteCapabilityRequestEvent.ifPresent(args -> args.recycle());
mRemoteCapabilityRequestEvent = Optional.empty();
@@ -489,14 +484,9 @@ public class UceController {
Optional<Boolean> unpublishEvent = mCachedCapabilityEvent.getUnpublishEvent();
unpublishEvent.ifPresent(unpublish -> onUnpublish());
- Optional<SomeArgs> publishUpdatedEvent = mCachedCapabilityEvent.getPublishUpdatedEvent();
- publishUpdatedEvent.ifPresent(args -> {
- int reasonCode = (Integer) args.arg1;
- String reasonPhrase = (String) args.arg2;
- int reasonHeaderCause = (Integer) args.arg3;
- String reasonHeaderText = (String) args.arg4;
- onPublishUpdated(reasonCode, reasonPhrase, reasonHeaderCause, reasonHeaderText);
- });
+ Optional<SipDetails> publishUpdatedEvent = mCachedCapabilityEvent.getPublishUpdatedEvent();
+ publishUpdatedEvent.ifPresent(details ->
+ onPublishUpdated(details));
Optional<SomeArgs> remoteRequest = mCachedCapabilityEvent.getRemoteCapabilityRequestEvent();
remoteRequest.ifPresent(args -> {
@@ -606,15 +596,12 @@ public class UceController {
}
@Override
- public void onPublishUpdated(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
+ public void onPublishUpdated(@NonNull SipDetails details) {
if (isRcsConnecting()) {
- mCachedCapabilityEvent.setOnPublishUpdatedEvent(reasonCode, reasonPhrase,
- reasonHeaderCause, reasonHeaderText);
+ mCachedCapabilityEvent.setOnPublishUpdatedEvent(details);
return;
}
- UceController.this.onPublishUpdated(reasonCode, reasonPhrase,
- reasonHeaderCause, reasonHeaderText);
+ UceController.this.onPublishUpdated(details);
}
@Override
@@ -648,14 +635,14 @@ public class UceController {
if (uriList == null || uriList.isEmpty() || c == null) {
logw("requestCapabilities: parameter is empty");
if (c != null) {
- c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
}
return;
}
if (isUnavailable()) {
logw("requestCapabilities: controller is unavailable");
- c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
return;
}
@@ -668,7 +655,7 @@ public class UceController {
long retryAfterMillis = deviceStateResult.getRequestRetryAfterMillis();
logw("requestCapabilities: The device is disallowed, deviceState= " + deviceState +
", errorCode=" + errorCode + ", retryAfterMillis=" + retryAfterMillis);
- c.onError(errorCode, retryAfterMillis);
+ c.onError(errorCode, retryAfterMillis, null);
return;
}
@@ -687,14 +674,14 @@ public class UceController {
if (uri == null || c == null) {
logw("requestAvailability: parameter is empty");
if (c != null) {
- c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
}
return;
}
if (isUnavailable()) {
logw("requestAvailability: controller is unavailable");
- c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ c.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
return;
}
@@ -707,7 +694,7 @@ public class UceController {
long retryAfterMillis = deviceStateResult.getRequestRetryAfterMillis();
logw("requestAvailability: The device is disallowed, deviceState= " + deviceState +
", errorCode=" + errorCode + ", retryAfterMillis=" + retryAfterMillis);
- c.onError(errorCode, retryAfterMillis);
+ c.onError(errorCode, retryAfterMillis, null);
return;
}
@@ -740,11 +727,9 @@ public class UceController {
* This method is triggered by the ImsService to notify framework that the device's
* publish status has been changed.
*/
- public void onPublishUpdated(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
+ public void onPublishUpdated(@NonNull SipDetails details) {
logi("onPublishUpdated");
- mPublishController.onPublishUpdated(reasonCode, reasonPhrase,
- reasonHeaderCause, reasonHeaderText);
+ mPublishController.onPublishUpdated(details);
}
/**
diff --git a/src/java/com/android/ims/rcs/uce/eab/EabBulkCapabilityUpdater.java b/src/java/com/android/ims/rcs/uce/eab/EabBulkCapabilityUpdater.java
index b4406fdd..738a4fc8 100644
--- a/src/java/com/android/ims/rcs/uce/eab/EabBulkCapabilityUpdater.java
+++ b/src/java/com/android/ims/rcs/uce/eab/EabBulkCapabilityUpdater.java
@@ -37,6 +37,7 @@ import android.telephony.CarrierConfigManager;
import android.telephony.ims.ImsManager;
import android.telephony.ims.ImsRcsManager;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import android.util.Log;
@@ -142,12 +143,12 @@ public final class EabBulkCapabilityUpdater {
}
@Override
- public void onComplete() {
+ public void onComplete(SipDetails details) {
Log.d(TAG, "onComplete");
}
@Override
- public void onError(int errorCode, long retryAfterMilliseconds) {
+ public void onError(int errorCode, long retryAfterMilliseconds, SipDetails details) {
Log.d(TAG, "Refresh capabilities failed. Error code: " + errorCode
+ ", retryAfterMilliseconds: " + retryAfterMilliseconds);
if (retryAfterMilliseconds != 0) {
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java b/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java
index dc794331..49291484 100644
--- a/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java
+++ b/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java
@@ -39,10 +39,13 @@ import android.util.Log;
import com.android.ims.rcs.uce.util.FeatureTags;
import com.android.ims.rcs.uce.util.UceUtils;
+import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
@@ -101,10 +104,14 @@ public class DeviceCapabilityInfo {
// Whether the settings are changed or not
private int mTtyPreferredMode;
- private boolean mAirplaneMode;
private boolean mMobileData;
private boolean mVtSetting;
+ // The service description associated with the last publication update.
+ private final Set<ServiceDescription> mLastSuccessfulCapabilities = new ArraySet<>();
+ // The service description to temporarily store the presence capability being sent.
+ private Set<ServiceDescription> mPendingPublishCapabilities;
+
public DeviceCapabilityInfo(int subId, String[] capToRegistrationMap) {
mSubId = subId;
mServiceCapRegTracker = PublishServiceDescTracker.fromCarrierConfig(capToRegistrationMap);
@@ -121,12 +128,13 @@ public class DeviceCapabilityInfo {
mRcsRegistered = false;
mRcsNetworkRegType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
mTtyPreferredMode = TelecomManager.TTY_MODE_OFF;
- mAirplaneMode = false;
mMobileData = true;
mVtSetting = true;
mMmTelCapabilities = new MmTelCapabilities();
mMmtelAssociatedUris = Collections.EMPTY_LIST;
mRcsAssociatedUris = Collections.EMPTY_LIST;
+ mLastSuccessfulCapabilities.clear();
+ mPendingPublishCapabilities = null;
}
/**
@@ -169,12 +177,17 @@ public class DeviceCapabilityInfo {
/**
* Update the status that IMS MMTEL is unregistered.
*/
- public synchronized void updateImsMmtelUnregistered() {
+ public synchronized boolean updateImsMmtelUnregistered() {
logi("IMS MMTEL unregistered: original state=" + mMmtelRegistered);
+ boolean changed = false;
if (mMmtelRegistered) {
mMmtelRegistered = false;
+ changed = true;
}
mMmtelNetworkRegType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ mLastSuccessfulCapabilities.clear();
+ mPendingPublishCapabilities = null;
+ return changed;
}
/**
@@ -242,7 +255,12 @@ public class DeviceCapabilityInfo {
mRcsRegistered = false;
changed = true;
}
+
+ mLastRegistrationFeatureTags = Collections.emptySet();
+ updateRegistration(mLastRegistrationFeatureTags);
mRcsNetworkRegType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ mLastSuccessfulCapabilities.clear();
+ mPendingPublishCapabilities = null;
return changed;
}
@@ -373,19 +391,6 @@ public class DeviceCapabilityInfo {
}
/**
- * Update airplane mode state.
- * @return {@code true} if the airplane mode is changed, {@code false} otherwise.
- */
- public synchronized boolean updateAirplaneMode(boolean state) {
- if (mAirplaneMode != state) {
- logd("Airplane mode changes from " + mAirplaneMode + " to " + state);
- mAirplaneMode = state;
- return true;
- }
- return false;
- }
-
- /**
* Update mobile data setting.
* @return {@code true} if the mobile data setting is changed, {@code false} otherwise.
*/
@@ -454,6 +459,67 @@ public class DeviceCapabilityInfo {
return mPresenceCapable;
}
+ // Get the device's capabilities with the PRESENCE mechanism.
+ public RcsContactUceCapability getChangedPresenceCapability(Context context) {
+ if (context == null) {
+ return null;
+ }
+ Set<ServiceDescription> capableFromReg =
+ mServiceCapRegTracker.copyRegistrationCapabilities();
+ if (isPresenceCapabilityChanged(capableFromReg)) {
+ RcsContactUceCapability rcsContactUceCapability = getPresenceCapabilities(context);
+ if (rcsContactUceCapability != null) {
+ mPendingPublishCapabilities = mServiceCapRegTracker.copyRegistrationCapabilities();
+ }
+ return rcsContactUceCapability;
+ }
+ return null;
+ }
+
+ public void setPresencePublishResult(boolean isSuccess) {
+ if (isSuccess) {
+ mLastSuccessfulCapabilities.clear();
+ if (mPendingPublishCapabilities != null) {
+ mLastSuccessfulCapabilities.addAll(mPendingPublishCapabilities);
+ }
+ }
+ mPendingPublishCapabilities = null;
+ }
+
+ public void resetPresenceCapability() {
+ mLastSuccessfulCapabilities.clear();
+ mPendingPublishCapabilities = null;
+ }
+
+ public List<RcsContactPresenceTuple> getLastSuccessfulPresenceTuplesWithoutContactUri() {
+ List<RcsContactPresenceTuple> presenceTuples = new ArrayList<>();
+ if (mLastSuccessfulCapabilities.isEmpty()) {
+ return presenceTuples;
+ }
+
+ for (ServiceDescription capability : mLastSuccessfulCapabilities) {
+ presenceTuples.add(capability.getTupleBuilder().build());
+ }
+ return presenceTuples;
+ }
+
+ @VisibleForTesting
+ public void addLastSuccessfulServiceDescription(ServiceDescription capability) {
+ mLastSuccessfulCapabilities.add(capability);
+ }
+
+ @VisibleForTesting
+ public boolean isPresenceCapabilityChanged(Set<ServiceDescription> capableFromReg) {
+ if (mLastSuccessfulCapabilities.isEmpty()) {
+ return true;
+ }
+
+ if (capableFromReg.equals(mLastSuccessfulCapabilities)) {
+ return false;
+ }
+ return true;
+ }
+
private boolean isVolteAvailable(int networkRegType, MmTelCapabilities capabilities) {
return (networkRegType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
&& capabilities.isCapable(MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE);
@@ -486,7 +552,12 @@ public class DeviceCapabilityInfo {
@CapabilityMechanism int mechanism, Context context) {
switch (mechanism) {
case RcsContactUceCapability.CAPABILITY_MECHANISM_PRESENCE:
- return getPresenceCapabilities(context);
+ RcsContactUceCapability rcsContactUceCapability = getPresenceCapabilities(context);
+ if (rcsContactUceCapability != null) {
+ mPendingPublishCapabilities =
+ mServiceCapRegTracker.copyRegistrationCapabilities();
+ }
+ return rcsContactUceCapability;
case RcsContactUceCapability.CAPABILITY_MECHANISM_OPTIONS:
return getOptionsCapabilities(context);
default:
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListener.java b/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListener.java
index 442cf7da..b58f7ec6 100644
--- a/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListener.java
+++ b/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListener.java
@@ -162,6 +162,8 @@ public class DeviceCapabilityListener {
public void sendImsUnregisteredMessage() {
logd("sendImsUnregisteredMessage");
+ // The IMS has been unregistered. Remove the existing message not processed.
+ removeMessages(EVENT_REQUEST_PUBLISH);
// Remove the existing message and resend a new message.
removeMessages(EVENT_IMS_UNREGISTERED);
Message msg = obtainMessage(EVENT_IMS_UNREGISTERED);
@@ -272,9 +274,9 @@ public class DeviceCapabilityListener {
private void registerReceivers() {
logd("registerReceivers");
IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
filter.addAction(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
- mContext.registerReceiver(mReceiver, filter);
+ mContext.registerReceiver(mReceiver, filter, android.Manifest.permission.MODIFY_PHONE_STATE,
+ null, Context.RECEIVER_EXPORTED);
ContentResolver resolver = mContext.getContentResolver();
if (resolver != null) {
@@ -389,11 +391,6 @@ public class DeviceCapabilityListener {
TelecomManager.TTY_MODE_OFF);
handleTtyPreferredModeChanged(preferredMode);
break;
-
- case Intent.ACTION_AIRPLANE_MODE_CHANGED:
- boolean airplaneMode = intent.getBooleanExtra("state", false);
- handleAirplaneModeChanged(airplaneMode);
- break;
}
}
};
@@ -492,7 +489,7 @@ public class DeviceCapabilityListener {
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
synchronized (mLock) {
logi("onRcsSubscriberAssociatedUriChanged");
- handleRcsSubscriberAssociatedUriChanged(uris, true);
+ handleRcsSubscriberAssociatedUriChanged(uris, false);
}
}
};
@@ -523,7 +520,7 @@ public class DeviceCapabilityListener {
public void onSubscriberAssociatedUriChanged(Uri[] uris) {
synchronized (mLock) {
logi("onMmTelSubscriberAssociatedUriChanged");
- handleMmTelSubscriberAssociatedUriChanged(uris, true);
+ handleMmTelSubscriberAssociatedUriChanged(uris, false);
}
}
};
@@ -571,15 +568,6 @@ public class DeviceCapabilityListener {
}
}
- private void handleAirplaneModeChanged(boolean state) {
- boolean isChanged = mCapabilityInfo.updateAirplaneMode(state);
- logi("Airplane mode changed: " + state + ", isChanged="+ isChanged);
- if (isChanged) {
- mHandler.sendTriggeringPublishMessage(
- PublishController.PUBLISH_TRIGGER_AIRPLANE_MODE_CHANGE);
- }
- }
-
private void handleMobileDataChanged(boolean isEnabled) {
boolean isChanged = mCapabilityInfo.updateMobileData(isEnabled);
logi("Mobile data changed: " + isEnabled + ", isChanged=" + isChanged);
@@ -602,18 +590,18 @@ public class DeviceCapabilityListener {
* This method is called when the MMTEL is registered.
*/
private void handleImsMmtelRegistered(int imsTransportType) {
+ // update capability, but not trigger PUBLISH message.
+ // PUBLISH message will be sent when the Capability status changed callback is called.
mCapabilityInfo.updateImsMmtelRegistered(imsTransportType);
- mHandler.sendTriggeringPublishMessage(
- PublishController.PUBLISH_TRIGGER_MMTEL_REGISTERED);
}
/*
* This method is called when the MMTEL is unregistered.
*/
private void handleImsMmtelUnregistered() {
- mCapabilityInfo.updateImsMmtelUnregistered();
+ boolean hasChanged = mCapabilityInfo.updateImsMmtelUnregistered();
// When the MMTEL is unregistered, the mmtel associated uri should be cleared.
- handleMmTelSubscriberAssociatedUriChanged(null, false);
+ handleMmTelSubscriberAssociatedUriChanged(null, hasChanged);
// If the RCS is already unregistered, it informs that the IMS is unregistered.
if (mCapabilityInfo.isImsRegistered() == false) {
@@ -624,16 +612,17 @@ public class DeviceCapabilityListener {
/*
* This method is called when the MMTEL associated uri has changed.
*/
- private void handleMmTelSubscriberAssociatedUriChanged(Uri[] uris, boolean triggerPublish) {
+ private void handleMmTelSubscriberAssociatedUriChanged(Uri[] uris, boolean regiChanged) {
Uri originalUri = mCapabilityInfo.getMmtelAssociatedUri();
mCapabilityInfo.updateMmTelAssociatedUri(uris);
Uri currentUri = mCapabilityInfo.getMmtelAssociatedUri();
- boolean hasChanged = !(Objects.equals(originalUri, currentUri));
- logi("handleMmTelSubscriberAssociatedUriChanged: triggerPublish=" + triggerPublish +
- ", hasChanged=" + hasChanged);
+ boolean hasChanged = regiChanged || !(Objects.equals(originalUri, currentUri));
- if (triggerPublish && hasChanged) {
+ logi("handleMmTelSubscriberAssociatedUriChanged: hasChanged=" + hasChanged);
+
+ // Send internal request to send a modification PUBLISH if the MMTEL or RCS is registered.
+ if (mCapabilityInfo.isImsRegistered() && hasChanged) {
mHandler.sendTriggeringPublishMessage(
PublishController.PUBLISH_TRIGGER_MMTEL_URI_CHANGE);
}
@@ -663,7 +652,7 @@ public class DeviceCapabilityListener {
private void handleImsRcsUnregistered() {
boolean hasChanged = mCapabilityInfo.updateImsRcsUnregistered();
// When the RCS is unregistered, the rcs associated uri should be cleared.
- handleRcsSubscriberAssociatedUriChanged(null, false);
+ handleRcsSubscriberAssociatedUriChanged(null, hasChanged);
// If the MMTEL is already unregistered, it informs that the IMS is unregistered.
if (mCapabilityInfo.isImsRegistered() == false) {
mHandler.sendImsUnregisteredMessage();
@@ -673,16 +662,17 @@ public class DeviceCapabilityListener {
/*
* This method is called when the RCS associated uri has changed.
*/
- private void handleRcsSubscriberAssociatedUriChanged(Uri[] uris, boolean triggerPublish) {
+ private void handleRcsSubscriberAssociatedUriChanged(Uri[] uris, boolean regiChanged) {
Uri originalUri = mCapabilityInfo.getRcsAssociatedUri();
mCapabilityInfo.updateRcsAssociatedUri(uris);
Uri currentUri = mCapabilityInfo.getRcsAssociatedUri();
- boolean hasChanged = !(Objects.equals(originalUri, currentUri));
- logi("handleRcsSubscriberAssociatedUriChanged: triggerPublish=" + triggerPublish +
- ", hasChanged=" + hasChanged);
+ boolean hasChanged = regiChanged || !(Objects.equals(originalUri, currentUri));
+
+ logi("handleRcsSubscriberAssociatedUriChanged: hasChanged=" + hasChanged);
- if (triggerPublish && hasChanged) {
+ // Send internal request to send a modification PUBLISH if the MMTEL or RCS is registered.
+ if (mCapabilityInfo.isImsRegistered() && hasChanged) {
mHandler.sendTriggeringPublishMessage(PublishController.PUBLISH_TRIGGER_RCS_URI_CHANGE);
}
}
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishController.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishController.java
index b20f5ceb..732a558b 100644
--- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishController.java
+++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishController.java
@@ -18,9 +18,11 @@ package com.android.ims.rcs.uce.presence.publish;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsContactUceCapability.CapabilityMechanism;
import android.telephony.ims.RcsUceAdapter.PublishState;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import com.android.ims.rcs.uce.ControllerBase;
@@ -45,53 +47,49 @@ public interface PublishController extends ControllerBase {
/** Publish trigger type: TTY preferred changes */
int PUBLISH_TRIGGER_TTY_PREFERRED_CHANGE = 3;
- /** Publish trigger type: Airplane mode changes */
- int PUBLISH_TRIGGER_AIRPLANE_MODE_CHANGE = 4;
-
/** Publish trigger type: Mobile data changes */
- int PUBLISH_TRIGGER_MOBILE_DATA_CHANGE = 5;
+ int PUBLISH_TRIGGER_MOBILE_DATA_CHANGE = 4;
/** Publish trigger type: VT setting changes */
- int PUBLISH_TRIGGER_VT_SETTING_CHANGE = 6;
+ int PUBLISH_TRIGGER_VT_SETTING_CHANGE = 5;
/** Publish trigger type: MMTEL registered */
- int PUBLISH_TRIGGER_MMTEL_REGISTERED = 7;
+ int PUBLISH_TRIGGER_MMTEL_REGISTERED = 6;
/** Publish trigger type: MMTEL unregistered */
- int PUBLISH_TRIGGER_MMTEL_UNREGISTERED = 8;
+ int PUBLISH_TRIGGER_MMTEL_UNREGISTERED = 7;
/** Publish trigger type: MMTEL capability changes */
- int PUBLISH_TRIGGER_MMTEL_CAPABILITY_CHANGE = 9;
+ int PUBLISH_TRIGGER_MMTEL_CAPABILITY_CHANGE = 8;
/** Publish trigger type: MMTEL associated uri changes */
- int PUBLISH_TRIGGER_MMTEL_URI_CHANGE = 10;
+ int PUBLISH_TRIGGER_MMTEL_URI_CHANGE = 9;
/** Publish trigger type: RCS registered */
- int PUBLISH_TRIGGER_RCS_REGISTERED = 11;
+ int PUBLISH_TRIGGER_RCS_REGISTERED = 10;
/** Publish trigger type: RCS unregistered */
- int PUBLISH_TRIGGER_RCS_UNREGISTERED = 12;
+ int PUBLISH_TRIGGER_RCS_UNREGISTERED = 11;
/** Publish trigger type: RCS associated uri changes */
- int PUBLISH_TRIGGER_RCS_URI_CHANGE = 13;
+ int PUBLISH_TRIGGER_RCS_URI_CHANGE = 12;
/** Publish trigger type: provisioning changes */
- int PUBLISH_TRIGGER_PROVISIONING_CHANGE = 14;
+ int PUBLISH_TRIGGER_PROVISIONING_CHANGE = 13;
/**The caps have been overridden for a test*/
- int PUBLISH_TRIGGER_OVERRIDE_CAPS = 15;
+ int PUBLISH_TRIGGER_OVERRIDE_CAPS = 14;
/** The Carrier Config for the subscription has Changed **/
- int PUBLISH_TRIGGER_CARRIER_CONFIG_CHANGED = 16;
+ int PUBLISH_TRIGGER_CARRIER_CONFIG_CHANGED = 15;
/** MMTEL and RCS are unregistered. **/
- int PUBLISH_TRIGGER_MMTEL_RCS_UNREGISTERED = 17;
+ int PUBLISH_TRIGGER_MMTEL_RCS_UNREGISTERED = 16;
@IntDef(value = {
PUBLISH_TRIGGER_SERVICE,
PUBLISH_TRIGGER_RETRY,
PUBLISH_TRIGGER_TTY_PREFERRED_CHANGE,
- PUBLISH_TRIGGER_AIRPLANE_MODE_CHANGE,
PUBLISH_TRIGGER_MOBILE_DATA_CHANGE,
PUBLISH_TRIGGER_VT_SETTING_CHANGE,
PUBLISH_TRIGGER_MMTEL_REGISTERED,
@@ -142,7 +140,8 @@ public interface PublishController extends ControllerBase {
/**
* Update the publish request result.
*/
- void updatePublishRequestResult(int publishState, Instant updatedTimestamp, String pidfXml);
+ void updatePublishRequestResult(int publishState, Instant updatedTimestamp, String pidfXml,
+ SipDetails details);
/**
* Update the value of the publish throttle.
@@ -212,9 +211,7 @@ public interface PublishController extends ControllerBase {
/**
* Notify that the device's publish status have been changed.
*/
- void onPublishUpdated(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText);
-
+ void onPublishUpdated(@NonNull SipDetails details);
/**
* Retrieve the device's capabilities.
*/
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 034d9ac2..101aa810 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
@@ -16,7 +16,10 @@
package com.android.ims.rcs.uce.presence.publish;
+import static android.telephony.ims.RcsUceAdapter.PUBLISH_STATE_OK;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
@@ -27,10 +30,13 @@ import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.telephony.CarrierConfigManager;
import android.telephony.ims.ImsException;
+import android.telephony.ims.PublishAttributes;
+import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsContactUceCapability.CapabilityMechanism;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.RcsUceAdapter.PublishState;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
@@ -53,6 +59,7 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.time.Instant;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@@ -198,7 +205,7 @@ public class PublishControllerImpl implements PublishController {
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;
+ return PUBLISH_STATE_OK;
} else {
return RcsUceAdapter.PUBLISH_STATE_OTHER_ERROR;
}
@@ -303,7 +310,7 @@ public class PublishControllerImpl implements PublishController {
boolean supportPublishingState) {
synchronized (mPublishStateLock) {
if (mIsDestroyedFlag) return;
- mPublishStateCallbacks.register(c, new Boolean(supportPublishingState));
+ mPublishStateCallbacks.register(c, Boolean.valueOf(supportPublishingState));
logd("registerPublishStateCallback: size="
+ mPublishStateCallbacks.getRegisteredCallbackCount());
}
@@ -363,11 +370,9 @@ public class PublishControllerImpl implements PublishController {
* Notify that the device's publish status have been changed.
*/
@Override
- public void onPublishUpdated(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
+ public void onPublishUpdated(@NonNull SipDetails details) {
if (mIsDestroyedFlag) return;
- mPublishHandler.sendPublishUpdatedMessage(reasonCode, reasonPhrase, reasonHeaderCause,
- reasonHeaderText);
+ mPublishHandler.sendPublishUpdatedMessage(details);
}
@Override
@@ -412,9 +417,10 @@ public class PublishControllerImpl implements PublishController {
@Override
public void updatePublishRequestResult(@PublishState int state,
- Instant updatedTime, String pidfXml) {
+ Instant updatedTime, String pidfXml, SipDetails details) {
logd("updatePublishRequestResult: " + state + ", time=" + updatedTime);
- mPublishHandler.sendPublishStateChangedMessage(state, updatedTime, pidfXml);
+ mPublishHandler.sendPublishStateChangedMessage(state, updatedTime, pidfXml,
+ details);
}
@Override
@@ -514,9 +520,10 @@ public class PublishControllerImpl implements PublishController {
int newPublishState = (Integer) args.arg1;
Instant updatedTimestamp = (Instant) args.arg2;
String pidfXml = (String) args.arg3;
+ SipDetails details = (SipDetails) args.arg4;
args.recycle();
publishCtrl.handlePublishStateChangedMessage(newPublishState, updatedTimestamp,
- pidfXml);
+ pidfXml, details);
break;
}
case MSG_NOTIFY_CURRENT_PUBLISH_STATE:
@@ -566,14 +573,8 @@ public class PublishControllerImpl implements PublishController {
break;
case MSG_PUBLISH_UPDATED: {
- SomeArgs args = (SomeArgs) message.obj;
- int reasonCode = (Integer) args.arg1;
- String reasonPhrase = (String) args.arg2;
- int reasonHeaderCause = (Integer) args.arg3;
- String reasonHeaderText = (String) args.arg4;
- args.recycle();
- publishCtrl.handlePublishUpdatedMessage(reasonCode, reasonPhrase,
- reasonHeaderCause, reasonHeaderText);
+ SipDetails details = (SipDetails) message.obj;
+ publishCtrl.handlePublishUpdatedMessage(details);
break;
}
@@ -654,7 +655,7 @@ public class PublishControllerImpl implements PublishController {
* Send the message to notify the publish state is changed.
*/
public void sendPublishStateChangedMessage(@PublishState int publishState,
- @NonNull Instant updatedTimestamp, String pidfXml) {
+ @NonNull Instant updatedTimestamp, String pidfXml, SipDetails details) {
PublishControllerImpl publishCtrl = mPublishControllerRef.get();
if (publishCtrl == null) return;
if (publishCtrl.mIsDestroyedFlag) return;
@@ -663,6 +664,7 @@ public class PublishControllerImpl implements PublishController {
args.arg1 = publishState;
args.arg2 = updatedTimestamp;
args.arg3 = pidfXml;
+ args.arg4 = details;
Message message = obtainMessage();
message.what = MSG_PUBLISH_STATE_CHANGED;
message.obj = args;
@@ -689,20 +691,14 @@ public class PublishControllerImpl implements PublishController {
/**
* Send the message to notify the publish state is changed.
*/
- public void sendPublishUpdatedMessage(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
+ public void sendPublishUpdatedMessage(@NonNull SipDetails details) {
PublishControllerImpl publishCtrl = mPublishControllerRef.get();
if (publishCtrl == null) return;
if (publishCtrl.mIsDestroyedFlag) return;
- SomeArgs args = SomeArgs.obtain();
- args.arg1 = reasonCode;
- args.arg2 = reasonPhrase;
- args.arg3 = reasonHeaderCause;
- args.arg4 = reasonHeaderText;
Message message = obtainMessage();
message.what = MSG_PUBLISH_UPDATED;
- message.obj = args;
+ message.obj = details;
sendMessage(message);
}
@@ -924,7 +920,7 @@ public class PublishControllerImpl implements PublishController {
// PUBLISH is enabled.
if (isPresencePublishEnabled()) {
handlePublishStateChangedMessage(RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED,
- Instant.now(), null /*pidfXml*/);
+ Instant.now(), null /*pidfXml*/, null /*SipDetails*/);
}
}
@@ -1011,7 +1007,8 @@ public class PublishControllerImpl implements PublishController {
// 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*/);
+ handlePublishStateChangedMessage(updatedPublishState, Instant.now(), null /*pidfxml*/,
+ null /*SipDetails*/);
}
}
@@ -1040,7 +1037,7 @@ public class PublishControllerImpl implements PublishController {
* from original state.
*/
private void handlePublishStateChangedMessage(@PublishState int newPublishState,
- Instant updatedTimestamp, String pidfXml) {
+ Instant updatedTimestamp, String pidfXml, SipDetails details) {
synchronized (mPublishStateLock) {
if (mIsDestroyedFlag) return;
// Check if the time of the given publish state is not earlier than existing time.
@@ -1067,7 +1064,7 @@ public class PublishControllerImpl implements PublishController {
logd("Notify publish state changed: " + mCurrentPublishState);
mPublishStateCallbacks.broadcast(c -> {
try {
- c.onPublishStateChanged(mCurrentPublishState);
+ c.onPublishUpdated(getPublishAttributes(mCurrentPublishState, details));
} catch (RemoteException e) {
logw("Notify publish state changed error: " + e);
}
@@ -1075,11 +1072,25 @@ public class PublishControllerImpl implements PublishController {
logd("Notify publish state changed: completed");
}
+ private PublishAttributes getPublishAttributes(@PublishState int mCurrentPublishState,
+ SipDetails details) {
+ List<RcsContactPresenceTuple> tuples = null;
+ if (mCurrentPublishState == PUBLISH_STATE_OK) {
+ tuples = mDeviceCapabilityInfo.getLastSuccessfulPresenceTuplesWithoutContactUri();
+ }
+ if (tuples != null && !tuples.isEmpty()) {
+ return new PublishAttributes.Builder(mCurrentPublishState).setSipDetails(details)
+ .setPresenceTuples(tuples).build();
+ }
+ return new PublishAttributes.Builder(mCurrentPublishState).setSipDetails(details).build();
+ }
+
private void handleNotifyCurrentPublishStateMessage(IRcsUcePublishStateCallback callback,
boolean supportPublishingState) {
if (mIsDestroyedFlag || callback == null) return;
try {
- callback.onPublishStateChanged(getUcePublishState(supportPublishingState));
+ int publishState = getUcePublishState(supportPublishingState);
+ callback.onPublishUpdated(getPublishAttributes(publishState, null /*SipDetails*/));
} catch (RemoteException e) {
logw("handleCurrentPublishStateUpdateMessage exception: " + e);
}
@@ -1146,7 +1157,8 @@ public class PublishControllerImpl implements PublishController {
Instant updatedTimestamp) {
if (mIsDestroyedFlag) return;
mPublishProcessor.resetState();
- handlePublishStateChangedMessage(newPublishState, updatedTimestamp, null);
+ handlePublishStateChangedMessage(newPublishState, updatedTimestamp,
+ null /*pidfXml*/, null /*SipDetails*/);
}
private void handlePublishSentMessage() {
@@ -1170,20 +1182,22 @@ public class PublishControllerImpl implements PublishController {
mCurrentPublishState = RcsUceAdapter.PUBLISH_STATE_PUBLISHING;
if (isSupportPublishingState) {
if (callback != null) {
- callback.onPublishStateChanged(mCurrentPublishState);
+ callback.onPublishUpdated(getPublishAttributes(mCurrentPublishState,
+ null /*SipDetails*/));
}
} else {
// If it is currently PUBLISH_STATE_OK, the state must not be changed to
// PUBLISH_STATE_NOT_PUBLISHED.
// And in the case of the current PUBLISH_STATE_NOT_PUBLISHED, it is
// necessary to avoid reporting the duplicate state.
- if (tempPublishState != RcsUceAdapter.PUBLISH_STATE_OK
+ if (tempPublishState != PUBLISH_STATE_OK
&& tempPublishState != RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED) {
// set the state to PUBLISH_STATE_NOT_PUBLISHED so that
// getUcePublishState is consistent with the callback
mLastPublishState = RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED;
if (callback != null) {
- callback.onPublishStateChanged(mLastPublishState);
+ callback.onPublishUpdated(getPublishAttributes(mLastPublishState,
+ null /*SipDetails*/));
}
}
}
@@ -1194,11 +1208,10 @@ public class PublishControllerImpl implements PublishController {
}
}
- private void handlePublishUpdatedMessage(int reasonCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
+ private void handlePublishUpdatedMessage(@NonNull SipDetails details) {
if (mIsDestroyedFlag) return;
PublishRequestResponse updatedPublish = new PublishRequestResponse(getLastPidfXml(),
- reasonCode, reasonPhrase, reasonHeaderCause, reasonHeaderText);
+ details);
mPublishProcessor.publishUpdated(updatedPublish);
}
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 d87eea9e..c239dd5a 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
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.content.Context;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
import android.text.TextUtils;
@@ -112,6 +113,8 @@ public class PublishProcessor {
logi("onRcsDisconnected");
mRcsFeatureManager = null;
mProcessorState.onRcsDisconnected();
+ // reset the publish capabilities.
+ mDeviceCapabilities.resetPresenceCapability();
}
/**
@@ -152,10 +155,15 @@ public class PublishProcessor {
}
// Get the latest device's capabilities.
- RcsContactUceCapability deviceCapability =
- mDeviceCapabilities.getDeviceCapabilities(CAPABILITY_MECHANISM_PRESENCE, mContext);
+ RcsContactUceCapability deviceCapability;
+ if (triggerType == PublishController.PUBLISH_TRIGGER_SERVICE) {
+ deviceCapability = mDeviceCapabilities.getDeviceCapabilities(
+ CAPABILITY_MECHANISM_PRESENCE, mContext);
+ } else {
+ deviceCapability = mDeviceCapabilities.getChangedPresenceCapability(mContext);
+ }
if (deviceCapability == null) {
- logw("doPublishInternal: device capability is null");
+ logi("doPublishInternal: device capability hasn't changed or is null");
return false;
}
@@ -349,6 +357,8 @@ public class PublishProcessor {
// Increase the retry count
mProcessorState.increaseRetryCount();
+ // reset the last capabilities because of the request is failed
+ mDeviceCapabilities.setPresencePublishResult(false);
// Reset the pending flag because it is going to resend a request.
clearPendingRequest();
@@ -373,15 +383,21 @@ public class PublishProcessor {
Instant responseTime = response.getResponseTimestamp();
// Record the time when the request is successful and reset the retry count.
+ boolean publishSuccess = false;
if (response.isRequestSuccess()) {
mProcessorState.setLastPublishedTime(responseTime);
mProcessorState.resetRetryCount();
+ publishSuccess = true;
}
+ // set the last capabilities according to the result of request.
+ mDeviceCapabilities.setPresencePublishResult(publishSuccess);
// Update the publish state after the request has finished.
int publishState = response.getPublishState();
String pidfXml = response.getPidfXml();
- mPublishCtrlCallback.updatePublishRequestResult(publishState, responseTime, pidfXml);
+ SipDetails details = response.getSipDetails().orElse(null);
+ mPublishCtrlCallback.updatePublishRequestResult(publishState, responseTime, pidfXml,
+ details);
// Refresh the device state with the publish request result.
response.getResponseSipCode().ifPresent(sipCode -> {
@@ -492,6 +508,8 @@ public class PublishProcessor {
*/
public void resetState() {
mProcessorState.resetState();
+ // reset the publish capabilities.
+ mDeviceCapabilities.resetPresenceCapability();
}
/**
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishRequestResponse.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishRequestResponse.java
index 47aa37c3..aa1b27c1 100644
--- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishRequestResponse.java
+++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishRequestResponse.java
@@ -16,8 +16,10 @@
package com.android.ims.rcs.uce.presence.publish;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IPublishResponseCallback;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
import android.text.TextUtils;
@@ -47,7 +49,7 @@ public class PublishRequestResponse {
private Optional<String> mReasonPhrase;
private Optional<Integer> mReasonHeaderCause;
private Optional<String> mReasonHeaderText;
-
+ private Optional<SipDetails> mSipDetails;
// The timestamp when receive the response from the network.
private Instant mResponseTimestamp;
@@ -61,29 +63,29 @@ public class PublishRequestResponse {
mReasonPhrase = Optional.empty();
mReasonHeaderCause = Optional.empty();
mReasonHeaderText = Optional.empty();
+ mSipDetails = Optional.empty();
}
- public PublishRequestResponse(String pidfXml, int sipCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
+ public PublishRequestResponse(String pidfXml, @Nullable SipDetails details) {
mTaskId = 0L;
mPublishCtrlCallback = null;
mCmdErrorCode = Optional.empty();
mPidfXml = pidfXml;
mResponseTimestamp = Instant.now();
- mNetworkRespSipCode = Optional.of(sipCode);
- mReasonPhrase = Optional.ofNullable(reasonPhrase);
- if (reasonHeaderCause != 0) {
- mReasonHeaderCause = Optional.of(reasonHeaderCause);
+ mNetworkRespSipCode = Optional.of(details.getResponseCode());
+ mReasonPhrase = Optional.ofNullable(details.getResponsePhrase());
+ if (details.getReasonHeaderCause() != 0) {
+ mReasonHeaderCause = Optional.of(details.getReasonHeaderCause());
} else {
mReasonHeaderCause = Optional.empty();
}
- if (TextUtils.isEmpty(reasonHeaderText)) {
+ if (TextUtils.isEmpty(details.getReasonHeaderText())) {
mReasonHeaderText = Optional.empty();
} else {
- mReasonHeaderText = Optional.ofNullable(reasonHeaderText);
+ mReasonHeaderText = Optional.ofNullable(details.getReasonHeaderText());
}
-
+ mSipDetails = Optional.ofNullable(details);
}
// The result callback of the publish capability request.
@@ -94,15 +96,8 @@ public class PublishRequestResponse {
}
@Override
- public void onNetworkResponse(int code, String reason) {
- PublishRequestResponse.this.onNetworkResponse(code, reason);
- }
-
- @Override
- public void onNetworkRespHeader(int code, String reasonPhrase, int reasonHeaderCause,
- String reasonHeaderText) {
- PublishRequestResponse.this.onNetworkResponse(code, reasonPhrase, reasonHeaderCause,
- reasonHeaderText);
+ public void onNetworkResponse(@NonNull SipDetails details) {
+ PublishRequestResponse.this.onNetworkResponse(details);
}
};
@@ -150,6 +145,12 @@ public class PublishRequestResponse {
}
/**
+ * Retrieve the sip information which received from the network.
+ */
+ public Optional<SipDetails> getSipDetails() {
+ return mSipDetails;
+ }
+ /**
* Retrieve the SIP code from the network response. It will get the value from the Reason
* Header first. If the ReasonHeader is not present, it will get the value from the Network
* response instead.
@@ -198,49 +199,34 @@ public class PublishRequestResponse {
}
}
- private void onNetworkResponse(int sipCode, String reason) {
+ private void onNetworkResponse(@NonNull SipDetails details) {
// When we send a request to PUBLISH and there is no change to the UCE capabilities, we
// expected onCommandError() with COMMAND_CODE_NO_CHANGE.
// But some of the vendor will instead send SIP code 999.
- if (sipCode == 999) {
+ if (details.getResponseCode() == 999) {
onCommandError(RcsCapabilityExchangeImplBase.COMMAND_CODE_NO_CHANGE);
return;
}
mResponseTimestamp = Instant.now();
- mNetworkRespSipCode = Optional.of(sipCode);
- mReasonPhrase = Optional.ofNullable(reason);
- updateRetryFlagByNetworkResponse();
-
- PublishControllerCallback ctrlCallback = mPublishCtrlCallback;
- if (ctrlCallback != null) {
- ctrlCallback.onRequestNetworkResp(this);
- } else {
- Log.d(LOG_TAG, "onNetworkResponse: already destroyed. sip code=" + sipCode);
+ mNetworkRespSipCode = Optional.of(details.getResponseCode());
+ mReasonPhrase = Optional.ofNullable(details.getResponsePhrase());
+ if (details.getReasonHeaderCause() != 0) {
+ mReasonHeaderCause = Optional.of(details.getReasonHeaderCause());
}
- }
-
- private void onNetworkResponse(int sipCode, String reasonPhrase, int reasonHeaderCause,
- String reasonHeaderText) {
- // When we send a request to PUBLISH and there is no change to the UCE capabilities, we
- // expected onCommandError() with COMMAND_CODE_NO_CHANGE.
- // But some of the vendor will instead send SIP code 999.
- if (sipCode == 999) {
- onCommandError(RcsCapabilityExchangeImplBase.COMMAND_CODE_NO_CHANGE);
- return;
+ if (TextUtils.isEmpty(details.getReasonHeaderText())) {
+ mReasonHeaderText = Optional.empty();
+ } else {
+ mReasonHeaderText = Optional.ofNullable(details.getReasonHeaderText());
}
- mResponseTimestamp = Instant.now();
- mNetworkRespSipCode = Optional.of(sipCode);
- mReasonPhrase = Optional.ofNullable(reasonPhrase);
- mReasonHeaderCause = Optional.of(reasonHeaderCause);
- mReasonHeaderText = Optional.ofNullable(reasonHeaderText);
+ mSipDetails = Optional.ofNullable(details);
updateRetryFlagByNetworkResponse();
PublishControllerCallback ctrlCallback = mPublishCtrlCallback;
if (ctrlCallback != null) {
ctrlCallback.onRequestNetworkResp(this);
} else {
- Log.d(LOG_TAG, "onNetworkResponse: already destroyed. sipCode=" + sipCode +
- ", reasonHeader=" + reasonHeaderCause);
+ Log.d(LOG_TAG, "onNetworkResponse: already destroyed. sip code="
+ + details.getResponseCode());
}
}
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTracker.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTracker.java
index a107b1ad..7f7ea3e6 100644
--- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTracker.java
+++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTracker.java
@@ -53,7 +53,7 @@ public class PublishServiceDescTracker {
*/
private static final Map<ServiceDescription, Set<String>> DEFAULT_SERVICE_DESCRIPTION_MAP;
static {
- ArrayMap<ServiceDescription, Set<String>> map = new ArrayMap<>(21);
+ ArrayMap<ServiceDescription, Set<String>> map = new ArrayMap<>(23);
map.put(ServiceDescription.SERVICE_DESCRIPTION_CHAT_IM,
Collections.singleton(FeatureTags.FEATURE_TAG_CHAT_IM));
map.put(ServiceDescription.SERVICE_DESCRIPTION_CHAT_SESSION,
@@ -111,6 +111,14 @@ public class PublishServiceDescTracker {
FeatureTags.FEATURE_TAG_CHATBOT_VERSION_V2_SUPPORTED)));
map.put(ServiceDescription.SERVICE_DESCRIPTION_CHATBOT_ROLE,
Collections.singleton(FeatureTags.FEATURE_TAG_CHATBOT_ROLE));
+ map.put(ServiceDescription.SERVICE_DESCRIPTION_SLM, new ArraySet<>(
+ Arrays.asList(FeatureTags.FEATURE_TAG_PAGER_MODE,
+ FeatureTags.FEATURE_TAG_LARGE_MODE,
+ FeatureTags.FEATURE_TAG_DEFERRED_MESSAGING,
+ FeatureTags.FEATURE_TAG_LARGE_PAGER_MODE)));
+ map.put(ServiceDescription.SERVICE_DESCRIPTION_SLM_PAGER_LARGE, new ArraySet<>(
+ Arrays.asList(FeatureTags.FEATURE_TAG_PAGER_MODE,
+ FeatureTags.FEATURE_TAG_LARGE_MODE)));
DEFAULT_SERVICE_DESCRIPTION_MAP = Collections.unmodifiableMap(map);
}
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/ServiceDescription.java b/src/java/com/android/ims/rcs/uce/presence/publish/ServiceDescription.java
index 0f271e1c..e175f2a4 100644
--- a/src/java/com/android/ims/rcs/uce/presence/publish/ServiceDescription.java
+++ b/src/java/com/android/ims/rcs/uce/presence/publish/ServiceDescription.java
@@ -169,6 +169,20 @@ public class ServiceDescription {
null /*description*/
);
+ public static final ServiceDescription SERVICE_DESCRIPTION_SLM =
+ new ServiceDescription(
+ RcsContactPresenceTuple.SERVICE_ID_SLM,
+ "2.0" /*version*/,
+ null /*description*/
+ );
+
+ public static final ServiceDescription SERVICE_DESCRIPTION_SLM_PAGER_LARGE =
+ new ServiceDescription(
+ RcsContactPresenceTuple.SERVICE_ID_SLM,
+ "2.0" /*version*/,
+ "Standalone Messaging" /*description*/
+ );
+
/** Mandatory "service-id" element */
public final @NonNull String serviceId;
/** Mandatory "version" element */
diff --git a/src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java b/src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java
index 97371b8b..6da31301 100644
--- a/src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java
+++ b/src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java
@@ -16,11 +16,14 @@
package com.android.ims.rcs.uce.request;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.Uri;
import android.telephony.ims.RcsContactTerminatedReason;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.RcsUceAdapter.ErrorCode;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.CommandCode;
import android.text.TextUtils;
@@ -85,6 +88,9 @@ public class CapabilityRequestResponse {
// The collection to record whether the request contacts have received the capabilities updated.
private Map<Uri, Boolean> mContactCapsReceived;
+ // The SIP detail information of the network response.
+ private Optional<SipDetails> mSipDetails;
+
public CapabilityRequestResponse() {
mRequestInternalError = Optional.empty();
mCommandError = Optional.empty();
@@ -99,6 +105,7 @@ public class CapabilityRequestResponse {
mUpdatedCapabilityList = new ArrayList<>();
mRemoteCaps = new HashSet<>();
mContactCapsReceived = new HashMap<>();
+ mSipDetails = Optional.empty();
}
/**
@@ -169,12 +176,20 @@ public class CapabilityRequestResponse {
/**
* Set the network response of this request which is sent by the network.
*/
- public synchronized void setNetworkResponseCode(int sipCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
- mNetworkRespSipCode = Optional.of(sipCode);
- mReasonPhrase = Optional.ofNullable(reasonPhrase);
- mReasonHeaderCause = Optional.of(reasonHeaderCause);
- mReasonHeaderText = Optional.ofNullable(reasonHeaderText);
+ public synchronized void setSipDetails(@NonNull SipDetails details) {
+ setNetworkResponseCode(details.getResponseCode(), details.getResponsePhrase());
+ if (details.getReasonHeaderCause() != 0) {
+ mReasonHeaderCause = Optional.of(details.getReasonHeaderCause());
+ } else {
+ mReasonHeaderCause = Optional.empty();
+ }
+ if (TextUtils.isEmpty(details.getReasonHeaderText())) {
+ mReasonHeaderText = Optional.empty();
+ } else {
+ mReasonHeaderText = Optional.ofNullable(details.getReasonHeaderText());
+ }
+
+ mSipDetails = Optional.ofNullable(details);
}
// Get the sip code of the network response.
@@ -239,6 +254,13 @@ public class CapabilityRequestResponse {
}
/**
+ * Retrieve the SIP information which received from the network.
+ */
+ public Optional<SipDetails> getSipDetails() {
+ return mSipDetails;
+ }
+
+ /**
* Add the capabilities which are retrieved from the cache.
*/
public synchronized void addCachedCapabilities(List<RcsContactUceCapability> capabilityList) {
diff --git a/src/java/com/android/ims/rcs/uce/request/OptionsRequestCoordinator.java b/src/java/com/android/ims/rcs/uce/request/OptionsRequestCoordinator.java
index a2660931..b2db1788 100644
--- a/src/java/com/android/ims/rcs/uce/request/OptionsRequestCoordinator.java
+++ b/src/java/com/android/ims/rcs/uce/request/OptionsRequestCoordinator.java
@@ -315,7 +315,7 @@ public class OptionsRequestCoordinator extends UceRequestCoordinator {
private void triggerCompletedCallback() {
try {
logd("triggerCompletedCallback");
- mCapabilitiesCallback.onComplete();
+ mCapabilitiesCallback.onComplete(null);
} catch (RemoteException e) {
logw("triggerCompletedCallback exception: " + e);
} finally {
@@ -329,7 +329,7 @@ public class OptionsRequestCoordinator extends UceRequestCoordinator {
private void triggerErrorCallback(int errorCode, long retryAfterMillis) {
try {
logd("triggerErrorCallback: errorCode=" + errorCode + ", retry=" + retryAfterMillis);
- mCapabilitiesCallback.onError(errorCode, retryAfterMillis);
+ mCapabilitiesCallback.onError(errorCode, retryAfterMillis, null);
} catch (RemoteException e) {
logw("triggerErrorCallback exception: " + e);
} finally {
diff --git a/src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java b/src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java
index bee71771..a306eb42 100644
--- a/src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java
+++ b/src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java
@@ -17,11 +17,13 @@
package com.android.ims.rcs.uce.request;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.RcsContactTerminatedReason;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.ISubscribeResponseCallback;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.CommandCode;
@@ -53,14 +55,8 @@ public class SubscribeRequest extends CapabilityRequest {
SubscribeRequest.this.onCommandError(code);
}
@Override
- public void onNetworkResponse(int code, String reason) {
- SubscribeRequest.this.onNetworkResponse(code, reason);
- }
- @Override
- public void onNetworkRespHeader(int code, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
- SubscribeRequest.this.onNetworkResponse(code, reasonPhrase, reasonHeaderCause,
- reasonHeaderText);
+ public void onNetworkResponse(@NonNull SipDetails details) {
+ SubscribeRequest.this.onNetworkResponse(details);
}
@Override
public void onNotifyCapabilitiesUpdate(List<String> pidfXmls) {
@@ -135,28 +131,14 @@ public class SubscribeRequest extends CapabilityRequest {
}
// Receive the network response callback which is triggered by ISubscribeResponseCallback.
- private void onNetworkResponse(int sipCode, String reason) {
- logd("onNetworkResponse: code=" + sipCode + ", reason=" + reason);
- if (mIsFinished) {
- logw("onNetworkResponse: request is already finished");
- return;
- }
- mRequestResponse.setNetworkResponseCode(sipCode, reason);
- mRequestManagerCallback.notifyNetworkResponse(mCoordinatorId, mTaskId);
- }
+ private void onNetworkResponse(@NonNull SipDetails details) {
+ logd("onNetworkResponse: sip details=" + details.toString());
- // Receive the network response callback which is triggered by ISubscribeResponseCallback.
- private void onNetworkResponse(int sipCode, String reasonPhrase,
- int reasonHeaderCause, String reasonHeaderText) {
- logd("onNetworkResponse: code=" + sipCode + ", reasonPhrase=" + reasonPhrase +
- ", reasonHeaderCause=" + reasonHeaderCause +
- ", reasonHeaderText=" + reasonHeaderText);
if (mIsFinished) {
logw("onNetworkResponse: request is already finished");
return;
}
- mRequestResponse.setNetworkResponseCode(sipCode, reasonPhrase, reasonHeaderCause,
- reasonHeaderText);
+ mRequestResponse.setSipDetails(details);
mRequestManagerCallback.notifyNetworkResponse(mCoordinatorId, mTaskId);
}
diff --git a/src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java b/src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java
index f44686ac..26143f94 100644
--- a/src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java
+++ b/src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java
@@ -18,10 +18,12 @@ package com.android.ims.rcs.uce.request;
import static android.telephony.ims.stub.RcsCapabilityExchangeImplBase.COMMAND_CODE_GENERIC_FAILURE;
+import android.annotation.Nullable;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import com.android.ims.rcs.uce.UceDeviceState.DeviceStateResult;
@@ -111,21 +113,25 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
private static final RequestResultCreator sNetworkRespErrorCreator = (taskId, response,
requestMgrCallback) -> {
DeviceStateResult deviceState = requestMgrCallback.getDeviceState();
+ SipDetails details = response.getSipDetails().orElse(null);
if (deviceState.isRequestForbidden()) {
int errorCode = deviceState.getErrorCode().orElse(RcsUceAdapter.ERROR_FORBIDDEN);
long retryAfter = deviceState.getRequestRetryAfterMillis();
- return RequestResult.createFailedResult(taskId, errorCode, retryAfter);
+ return RequestResult.createFailedResult(taskId, errorCode, retryAfter, details);
} else {
int errorCode = CapabilityRequestResponse.getCapabilityErrorFromSipCode(response);
long retryAfter = response.getRetryAfterMillis();
- return RequestResult.createFailedResult(taskId, errorCode, retryAfter);
+ return RequestResult.createFailedResult(taskId, errorCode, retryAfter, details);
}
};
// The RequestResult creator of the network response is not 200 OK, however, we can to treat
// it as a successful result and finish the request
private static final RequestResultCreator sNetworkRespSuccessfulCreator = (taskId, response,
- requestMgrCallback) -> RequestResult.createSuccessResult(taskId);
+ requestMgrCallback) -> {
+ SipDetails detail = response.getSipDetails().orElse(null);
+ return RequestResult.createSuccessResult(taskId, detail);
+ };
// The RequestResult creator of the request terminated.
private static final RequestResultCreator sTerminatedCreator = (taskId, response,
@@ -134,6 +140,7 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
TerminatedResult terminatedResult = SubscriptionTerminatedHelper.getAnalysisResult(
response.getTerminatedReason(), response.getRetryAfterMillis(),
response.haveAllRequestCapsUpdatedBeenReceived());
+ SipDetails details = response.getSipDetails().orElse(null);
if (terminatedResult.getErrorCode().isPresent()) {
// If the terminated error code is present, it means that the request is failed.
int errorCode = terminatedResult.getErrorCode().get();
@@ -143,9 +150,9 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
// If the network response is failed or the retryAfter is not 0, this request is failed.
long retryAfterMillis = response.getRetryAfterMillis();
int errorCode = CapabilityRequestResponse.getCapabilityErrorFromSipCode(response);
- return RequestResult.createFailedResult(taskId, errorCode, retryAfterMillis);
+ return RequestResult.createFailedResult(taskId, errorCode, retryAfterMillis, details);
} else {
- return RequestResult.createSuccessResult(taskId);
+ return RequestResult.createSuccessResult(taskId, details);
}
};
@@ -297,7 +304,9 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
// Trigger capabilities updated callback if there is any.
List<RcsContactUceCapability> updatedCapList = response.getUpdatedContactCapability();
if (!updatedCapList.isEmpty()) {
- mRequestManagerCallback.saveCapabilities(updatedCapList);
+ if (response.isNotFound()) {
+ mRequestManagerCallback.saveCapabilities(updatedCapList);
+ }
triggerCapabilitiesReceivedCallback(updatedCapList);
response.removeUpdatedCapabilities(updatedCapList);
}
@@ -538,14 +547,23 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
.max(Comparator.comparingLong(result ->
result.getRetryMillis().orElse(-1L)));
+ Optional<RequestResult> optDebugInfoResult = mFinishedRequests.values().stream()
+ .filter(result -> !result.getSipDetails().isEmpty())
+ .findFirst();
+
+ SipDetails details = null;
+ if (optDebugInfoResult.isPresent()) {
+ RequestResult result = optDebugInfoResult.get();
+ details = result.getSipDetails().orElse(null);
+ }
// Trigger the callback
if (optRequestResult.isPresent()) {
RequestResult result = optRequestResult.get();
int errorCode = result.getErrorCode().orElse(DEFAULT_ERROR_CODE);
long retryAfter = result.getRetryMillis().orElse(0L);
- triggerErrorCallback(errorCode, retryAfter);
+ triggerErrorCallback(errorCode, retryAfter, details);
} else {
- triggerCompletedCallback();
+ triggerCompletedCallback(details);
}
// Notify UceRequestManager to remove this instance from the collection.
@@ -572,10 +590,10 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
/**
* Trigger the onComplete callback to notify the request is completed.
*/
- private void triggerCompletedCallback() {
+ private void triggerCompletedCallback(@Nullable SipDetails details) {
try {
logd("triggerCompletedCallback");
- mCapabilitiesCallback.onComplete();
+ mCapabilitiesCallback.onComplete(details);
} catch (RemoteException e) {
logw("triggerCompletedCallback exception: " + e);
} finally {
@@ -586,10 +604,11 @@ public class SubscribeRequestCoordinator extends UceRequestCoordinator {
/**
* Trigger the onError callback to notify the request is failed.
*/
- private void triggerErrorCallback(int errorCode, long retryAfterMillis) {
+ private void triggerErrorCallback(int errorCode, long retryAfterMillis,
+ @Nullable SipDetails details) {
try {
logd("triggerErrorCallback: errorCode=" + errorCode + ", retry=" + retryAfterMillis);
- mCapabilitiesCallback.onError(errorCode, retryAfterMillis);
+ mCapabilitiesCallback.onError(errorCode, retryAfterMillis, details);
} catch (RemoteException e) {
logw("triggerErrorCallback exception: " + e);
} finally {
diff --git a/src/java/com/android/ims/rcs/uce/request/UceRequestCoordinator.java b/src/java/com/android/ims/rcs/uce/request/UceRequestCoordinator.java
index eea4fbe3..5d3a35da 100644
--- a/src/java/com/android/ims/rcs/uce/request/UceRequestCoordinator.java
+++ b/src/java/com/android/ims/rcs/uce/request/UceRequestCoordinator.java
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.SipDetails;
import android.util.Log;
import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
@@ -135,6 +136,15 @@ public abstract class UceRequestCoordinator {
}
/**
+ * Create a RequestResult that successfully completes the request.
+ * @param taskId the task id of the UceRequest
+ * @param details The SIP information related to this request.
+ */
+ public static RequestResult createSuccessResult(long taskId, @Nullable SipDetails details) {
+ return new RequestResult(taskId, details);
+ }
+
+ /**
* Create a RequestResult for the failed request.
* @param taskId the task id of the UceRequest
* @param errorCode the error code of the failed request
@@ -144,29 +154,66 @@ public abstract class UceRequestCoordinator {
return new RequestResult(taskId, errorCode, retry);
}
+ /**
+ * Create a RequestResult for the failed request.
+ * @param taskId the task id of the UceRequest
+ * @param errorCode the error code of the failed request
+ * @param retry When the request can be retried.
+ * @param details The SIP information related to this request.
+ */
+ public static RequestResult createFailedResult(long taskId, int errorCode, long retry,
+ @Nullable SipDetails details) {
+ return new RequestResult(taskId, errorCode, retry, details);
+ }
+
private final Long mTaskId;
private final Boolean mIsSuccess;
private final Optional<Integer> mErrorCode;
private final Optional<Long> mRetryMillis;
+ private final Optional<SipDetails> mSipDetails;
/**
* The private constructor for the successful request.
*/
private RequestResult(long taskId) {
+ this(taskId, null);
+ }
+
+ /**
+ * The private constructor for the successful request.
+ */
+ private RequestResult(long taskId, SipDetails details) {
mTaskId = taskId;
mIsSuccess = true;
mErrorCode = Optional.empty();
mRetryMillis = Optional.empty();
+ if (details == null) {
+ mSipDetails = Optional.empty();
+ } else {
+ mSipDetails = Optional.ofNullable(details);
+ }
}
/**
* The private constructor for the failed request.
*/
private RequestResult(long taskId, int errorCode, long retryMillis) {
+ this(taskId, errorCode, retryMillis, null);
+ }
+
+ /**
+ * The private constructor for the failed request.
+ */
+ private RequestResult(long taskId, int errorCode, long retryMillis, SipDetails details) {
mTaskId = taskId;
mIsSuccess = false;
mErrorCode = Optional.of(errorCode);
mRetryMillis = Optional.of(retryMillis);
+ if (details == null) {
+ mSipDetails = Optional.empty();
+ } else {
+ mSipDetails = Optional.ofNullable(details);
+ }
}
public long getTaskId() {
@@ -184,6 +231,10 @@ public abstract class UceRequestCoordinator {
public Optional<Long> getRetryMillis() {
return mRetryMillis;
}
+
+ public Optional<SipDetails> getSipDetails() {
+ return mSipDetails;
+ }
}
// The default capability error code.
diff --git a/src/java/com/android/ims/rcs/uce/request/UceRequestManager.java b/src/java/com/android/ims/rcs/uce/request/UceRequestManager.java
index 85908f0c..8ff39c1b 100644
--- a/src/java/com/android/ims/rcs/uce/request/UceRequestManager.java
+++ b/src/java/com/android/ims/rcs/uce/request/UceRequestManager.java
@@ -478,7 +478,7 @@ public class UceRequestManager {
public void sendCapabilityRequest(List<Uri> uriList, boolean skipFromCache,
IRcsUceControllerCallback callback) throws RemoteException {
if (mIsDestroyed) {
- callback.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ callback.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
return;
}
sendRequestInternal(UceRequest.REQUEST_TYPE_CAPABILITY, uriList, skipFromCache, callback);
@@ -490,7 +490,7 @@ public class UceRequestManager {
public void sendAvailabilityRequest(Uri uri, IRcsUceControllerCallback callback)
throws RemoteException {
if (mIsDestroyed) {
- callback.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ callback.onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
return;
}
sendRequestInternal(UceRequest.REQUEST_TYPE_AVAILABILITY,
@@ -511,7 +511,7 @@ public class UceRequestManager {
}
if (nonCachedUris.isEmpty()) {
logd("sendRequestInternal: shortcut complete, sending success result");
- callback.onComplete();
+ callback.onComplete(null);
return;
}
}
@@ -525,7 +525,7 @@ public class UceRequestManager {
if (requestCoordinator == null) {
logw("sendRequestInternal: Neither Presence nor OPTIONS are supported");
- callback.onError(RcsUceAdapter.ERROR_NOT_ENABLED, 0L);
+ callback.onError(RcsUceAdapter.ERROR_NOT_ENABLED, 0L, null);
return;
}
diff --git a/src/java/com/android/ims/rcs/uce/util/FeatureTags.java b/src/java/com/android/ims/rcs/uce/util/FeatureTags.java
index 8dbceda6..ed2eef4a 100644
--- a/src/java/com/android/ims/rcs/uce/util/FeatureTags.java
+++ b/src/java/com/android/ims/rcs/uce/util/FeatureTags.java
@@ -35,6 +35,18 @@ public class FeatureTags {
+ "service.ims.icsi.oma.cpm.largemsg,urn%3Aurn-7%3A3gpp-"
+ "service.ims.icsi.oma.cpm.deferred\";+g.gsma.rcs.cpm.pager-large";
+ public static final String FEATURE_TAG_PAGER_MODE =
+ "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg\"";
+
+ public static final String FEATURE_TAG_LARGE_MODE =
+ "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.largemsg\"";
+
+ public static final String FEATURE_TAG_DEFERRED_MESSAGING =
+ "+g.3gpp.icsi-ref=\"urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.deferred\"";
+
+ public static final String FEATURE_TAG_LARGE_PAGER_MODE =
+ "+g.gsma.rcs.cpm.pager-large";
+
public static final String FEATURE_TAG_CHAT_IM =
"+g.3gpp.iari-ref=\"urn%3Aurn-7%3A3gpp-application.ims.iari.rcse.im\"";
diff --git a/tests/Android.bp b/tests/Android.bp
index 82c303d5..7ae66b56 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -40,6 +40,7 @@ android_test {
],
test_suites: [
- "device-tests"
- ]
+ "device-tests",
+ ],
+ min_sdk_version: "29",
}
diff --git a/tests/src/com/android/ims/ContextFixture.java b/tests/src/com/android/ims/ContextFixture.java
index e987b387..21dd6348 100644
--- a/tests/src/com/android/ims/ContextFixture.java
+++ b/tests/src/com/android/ims/ContextFixture.java
@@ -33,6 +33,7 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.net.ConnectivityManager;
+import android.os.Handler;
import android.os.PersistableBundle;
import android.telecom.TelecomManager;
import android.telephony.CarrierConfigManager;
@@ -131,6 +132,18 @@ public class ContextFixture {
}
@Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler) {
+ return null;
+ }
+
+ @Override
+ public Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter,
+ String broadcastPermission, Handler scheduler, int flags) {
+ return null;
+ }
+
+ @Override
public void unregisterReceiver(BroadcastReceiver receiver) {
}
diff --git a/tests/src/com/android/ims/ImsManagerTest.java b/tests/src/com/android/ims/ImsManagerTest.java
index 0653908d..ad5051be 100644
--- a/tests/src/com/android/ims/ImsManagerTest.java
+++ b/tests/src/com/android/ims/ImsManagerTest.java
@@ -119,7 +119,7 @@ public class ImsManagerTest extends ImsTestBase {
doReturn(true).when(mSubscriptionManagerProxy).isValidSubscriptionId(anyInt());
doReturn(mSubId).when(mSubscriptionManagerProxy).getActiveSubscriptionIdList();
- doReturn(mSubId).when(mSubscriptionManagerProxy).getSubscriptionIds(anyInt());
+ doReturn(mSubId[0]).when(mSubscriptionManagerProxy).getSubscriptionId(anyInt());
doReturn(mPhoneId).when(mSubscriptionManagerProxy).getDefaultVoicePhoneId();
doReturn(-1).when(mSubscriptionManagerProxy).getIntegerSubscriptionProperty(anyInt(),
anyString(), anyInt());
@@ -1012,6 +1012,14 @@ public class ImsManagerTest extends ImsTestBase {
}
+ @Test @SmallTest
+ public void onMemoryAvailableTest() throws Exception{
+ ImsManager imsManager = getImsManagerAndInitProvisionedValues();
+ int token = 1;
+ imsManager.onMemoryAvailable(token);
+ verify(mMmTelFeatureConnection).onMemoryAvailable(eq(token));
+ }
+
private ImsManager getImsManagerAndInitProvisionedValues() {
when(mImsConfigImplBaseMock.getConfigInt(anyInt()))
.thenAnswer(invocation -> {
diff --git a/tests/src/com/android/ims/rcs/uce/UceControllerTest.java b/tests/src/com/android/ims/rcs/uce/UceControllerTest.java
index 021a7c10..79702ed5 100644
--- a/tests/src/com/android/ims/rcs/uce/UceControllerTest.java
+++ b/tests/src/com/android/ims/rcs/uce/UceControllerTest.java
@@ -147,7 +147,7 @@ public class UceControllerTest extends ImsTestBase {
List<Uri> uriList = new ArrayList<>();
uceController.requestCapabilities(uriList, mCapabilitiesCallback);
- verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
verify(mTaskManager, never()).sendCapabilityRequest(any(), eq(false), any());
}
@@ -164,7 +164,7 @@ public class UceControllerTest extends ImsTestBase {
uriList.add(Uri.fromParts("sip", "test", null));
uceController.requestCapabilities(uriList, mCapabilitiesCallback);
- verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_FORBIDDEN, 0L);
+ verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_FORBIDDEN, 0L, null);
verify(mTaskManager, never()).sendCapabilityRequest(any(), eq(false), any());
}
@@ -194,7 +194,7 @@ public class UceControllerTest extends ImsTestBase {
Uri contact = Uri.fromParts("sip", "test", null);
uceController.requestAvailability(contact, mCapabilitiesCallback);
- verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
verify(mTaskManager, never()).sendAvailabilityRequest(any(), any());
}
@@ -210,7 +210,7 @@ public class UceControllerTest extends ImsTestBase {
Uri contact = Uri.fromParts("sip", "test", null);
uceController.requestAvailability(contact, mCapabilitiesCallback);
- verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_FORBIDDEN, 0L);
+ verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_FORBIDDEN, 0L, null);
verify(mTaskManager, never()).sendCapabilityRequest(any(), eq(false), any());
}
diff --git a/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java b/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java
index c977a080..de045de4 100644
--- a/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java
+++ b/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java
@@ -16,6 +16,19 @@
package com.android.ims.rcs.uce.presence.publish;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.doReturn;
+
+import android.content.Context;
+import android.telephony.CarrierConfigManager;
+import android.telephony.TelephonyManager;
+import android.telephony.ims.RcsContactPresenceTuple;
+import android.util.ArraySet;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -26,6 +39,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import com.android.ims.ImsTestBase;
+import com.android.ims.rcs.uce.util.UceUtils;
import org.junit.After;
import org.junit.Before;
@@ -33,11 +47,18 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
@RunWith(AndroidJUnit4.class)
public class DeviceCapabilityInfoTest extends ImsTestBase {
-
int mSubId = 1;
+ @Mock PublishServiceDescTracker mPublishServiceDescTracker;
+ @Mock Context mMockContext;
+
String sipNumber = "123456789";
String telNumber = "987654321";
@@ -53,6 +74,22 @@ public class DeviceCapabilityInfoTest extends ImsTestBase {
@Test
@SmallTest
+ public void testGetPresenceCapabilityForSameDescription() throws Exception {
+ DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();
+
+ Set<ServiceDescription> mTestCapability = new ArraySet<>();
+ mTestCapability.add(getChatDescription());
+ mTestCapability.add(getMmtelDescription());
+ mTestCapability.add(getUndefinedDescription());
+
+ deviceCapInfo.addLastSuccessfulServiceDescription(getMmtelDescription());
+ deviceCapInfo.addLastSuccessfulServiceDescription(getChatDescription());
+ deviceCapInfo.addLastSuccessfulServiceDescription(getUndefinedDescription());
+ assertFalse(deviceCapInfo.isPresenceCapabilityChanged(mTestCapability));
+ }
+
+ @Test
+ @SmallTest
public void testGetImsAssociatedUriWithoutPreferTelUri() throws Exception {
DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();
@@ -90,6 +127,23 @@ public class DeviceCapabilityInfoTest extends ImsTestBase {
@Test
@SmallTest
+ public void testGetPresenceCapabilityForSameSizeOfDescription() throws Exception {
+ DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();
+
+ Set<ServiceDescription> mTestCapability = new ArraySet<>();
+ mTestCapability.add(getChatDescription());
+ mTestCapability.add(getMmtelDescription());
+ mTestCapability.add(getUndefinedDescription());
+
+ deviceCapInfo.addLastSuccessfulServiceDescription(getMmtelDescription());
+ deviceCapInfo.addLastSuccessfulServiceDescription(getChatDescription());
+ deviceCapInfo.addLastSuccessfulServiceDescription(getUndefined2Description());
+
+ assertTrue(deviceCapInfo.isPresenceCapabilityChanged(mTestCapability));
+ }
+
+ @Test
+ @SmallTest
public void testGetImsAssociatedUriWithPreferTelUri() throws Exception {
DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();
@@ -138,7 +192,43 @@ public class DeviceCapabilityInfoTest extends ImsTestBase {
number = numberParts[0];
assertEquals(number, telNumber);
+ }
+ @Test
+ @SmallTest
+ public void testGetLastSuccessfulPresenceTuples() throws Exception {
+ DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo();
+
+ List<RcsContactPresenceTuple> tuples =
+ deviceCapInfo.getLastSuccessfulPresenceTuplesWithoutContactUri();
+ // Verify that the presence tuples are empty when the last capabilities are empty.
+ assertTrue(tuples.isEmpty());
+
+ doReturn(null).when(mMockContext).getSystemService(CarrierConfigManager.class);
+ doReturn(null).when(mMockContext).getSystemService(TelephonyManager.class);
+ ServiceDescription mmtelDescription = getMmtelDescription();
+ deviceCapInfo.addLastSuccessfulServiceDescription(mmtelDescription);
+ ServiceDescription chatDescription = getChatDescription();
+ deviceCapInfo.addLastSuccessfulServiceDescription(chatDescription);
+ tuples = deviceCapInfo.getLastSuccessfulPresenceTuplesWithoutContactUri();
+ assertEquals(2, tuples.size());
+
+ Uri[] uris = new Uri[1];
+ uris[0] = Uri.fromParts(PhoneAccount.SCHEME_SIP, sipNumber, null);
+ deviceCapInfo.updateRcsAssociatedUri(uris);
+ List<RcsContactPresenceTuple> expectedTuples = new ArrayList<>();
+ expectedTuples.add(mmtelDescription.getTupleBuilder().setContactUri(uris[0]).build());
+ expectedTuples.add(chatDescription.getTupleBuilder().setContactUri(uris[0]).build());
+
+ tuples = deviceCapInfo.getLastSuccessfulPresenceTuplesWithoutContactUri();
+ assertTrue(!tuples.isEmpty());
+ assertEquals(expectedTuples.size(), tuples.size());
+ for (int i = 0; i < tuples.size(); i++) {
+ assertEquals(expectedTuples.get(i).getServiceId(), tuples.get(i).getServiceId());
+ assertEquals(expectedTuples.get(i).getServiceVersion(),
+ tuples.get(i).getServiceVersion());
+ assertNull(tuples.get(i).getContactUri());
+ }
}
private DeviceCapabilityInfo createDeviceCapabilityInfo() {
@@ -146,4 +236,40 @@ public class DeviceCapabilityInfoTest extends ImsTestBase {
return deviceCapInfo;
}
+ private ServiceDescription getChatDescription() {
+ ServiceDescription SERVICE_DESCRIPTION_CHAT_SESSION =
+ new ServiceDescription(
+ RcsContactPresenceTuple.SERVICE_ID_CHAT_V2,
+ "2.0" /*version*/,
+ null /*description*/
+ );
+ return SERVICE_DESCRIPTION_CHAT_SESSION;
+ }
+
+ private ServiceDescription getMmtelDescription() {
+ ServiceDescription SERVICE_DESCRIPTION_MMTEL_VOICE = new ServiceDescription(
+ RcsContactPresenceTuple.SERVICE_ID_MMTEL,
+ "1.0" /*version*/,
+ "Voice Service" /*description*/
+ );
+ return SERVICE_DESCRIPTION_MMTEL_VOICE;
+ }
+
+ private ServiceDescription getUndefinedDescription() {
+ ServiceDescription SERVICE_DESCRIPTION_TEST = new ServiceDescription(
+ "test",
+ "1.0" /*version*/,
+ "Test_Service" /*description*/
+ );
+ return SERVICE_DESCRIPTION_TEST;
+ }
+
+ private ServiceDescription getUndefined2Description() {
+ ServiceDescription SERVICE_DESCRIPTION_TEST2 = new ServiceDescription(
+ "test1",
+ "1.0" /*version*/,
+ "Test_Service" /*description*/
+ );
+ return SERVICE_DESCRIPTION_TEST2;
+ }
} \ No newline at end of file
diff --git a/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListenerTest.java b/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListenerTest.java
index 2d170ab6..11350393 100644
--- a/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListenerTest.java
+++ b/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityListenerTest.java
@@ -84,7 +84,6 @@ public class DeviceCapabilityListenerTest extends ImsTestBase {
getProvisioningManager(anyInt());
doReturn(true).when(mDeviceCapability).updateTtyPreferredMode(anyInt());
- doReturn(true).when(mDeviceCapability).updateAirplaneMode(anyBoolean());
doReturn(true).when(mDeviceCapability).updateMobileData(anyBoolean());
doReturn(true).when(mDeviceCapability).updateVtSetting(anyBoolean());
doReturn(true).when(mDeviceCapability).updateVtSetting(anyBoolean());
@@ -107,7 +106,8 @@ public class DeviceCapabilityListenerTest extends ImsTestBase {
deviceCapListener.initialize();
- verify(mContext).registerReceiver(any(), any());
+ verify(mContext).registerReceiver(any(), any(),
+ eq(android.Manifest.permission.MODIFY_PHONE_STATE), any(), anyInt());
verify(mProvisioningManager).registerProvisioningChangedCallback(any(), any());
}
@@ -143,23 +143,6 @@ public class DeviceCapabilityListenerTest extends ImsTestBase {
@Test
@SmallTest
- public void testAirplaneModeChange() throws Exception {
- DeviceCapabilityListener deviceCapListener = createDeviceCapabilityListener();
- final BroadcastReceiver receiver = deviceCapListener.mReceiver;
-
- Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- receiver.onReceive(mContext, intent);
-
- Handler handler = deviceCapListener.getHandler();
- waitForHandlerActionDelayed(handler, HANDLER_WAIT_TIMEOUT_MS, HANDLER_SENT_DELAY_MS);
-
- verify(mDeviceCapability).updateAirplaneMode(anyBoolean());
- verify(mCallback).requestPublishFromInternal(
- PublishController.PUBLISH_TRIGGER_AIRPLANE_MODE_CHANGE);
- }
-
- @Test
- @SmallTest
public void testMmtelRegistration() throws Exception {
DeviceCapabilityListener deviceCapListener = createDeviceCapabilityListener();
deviceCapListener.setImsCallbackRegistered(true);
@@ -171,7 +154,8 @@ public class DeviceCapabilityListenerTest extends ImsTestBase {
waitForHandlerActionDelayed(handler, HANDLER_WAIT_TIMEOUT_MS, HANDLER_SENT_DELAY_MS);
verify(mDeviceCapability).updateImsMmtelRegistered(1);
- verify(mCallback).requestPublishFromInternal(
+ // update capability, but not trigger PUBLISH message when MmTel registered.
+ verify(mCallback, never()).requestPublishFromInternal(
PublishController.PUBLISH_TRIGGER_MMTEL_REGISTERED);
}
@@ -266,6 +250,65 @@ public class DeviceCapabilityListenerTest extends ImsTestBase {
verify(mCallback).updateImsUnregistered();
}
+ @Test
+ @SmallTest
+ public void testRcsAndMmtelUnregistration() throws Exception {
+ DeviceCapabilityListener deviceCapListener = createDeviceCapabilityListener();
+ deviceCapListener.setImsCallbackRegistered(true);
+
+ Handler handler = deviceCapListener.getHandler();
+ ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, -1, "");
+ // RCS unregistered
+ RegistrationCallback rcsRegiCallback = deviceCapListener.mRcsRegistrationCallback;
+
+ doReturn(true).when(mDeviceCapability).updateImsRcsUnregistered();
+ // RCS is unregistered but MMTEL is registered.
+ doReturn(true).when(mDeviceCapability).isImsRegistered();
+ rcsRegiCallback.onUnregistered(info);
+
+ // MMTEL unregistered
+ RegistrationCallback mmtelRegiCallback = deviceCapListener.mMmtelRegistrationCallback;
+ // set the Ims is unregistered
+ doReturn(false).when(mDeviceCapability).isImsRegistered();
+ mmtelRegiCallback.onUnregistered(info);
+
+ waitForHandlerActionDelayed(handler, HANDLER_WAIT_TIMEOUT_MS, HANDLER_SENT_DELAY_MS);
+
+ // Do not send internal publish trigger
+ verify(mCallback, never()).requestPublishFromInternal(anyInt());
+ // IMS is unregistered. Verify send ImsUnregistered.
+ verify(mCallback).updateImsUnregistered();
+ }
+
+ @Test
+ @SmallTest
+ public void testUnregisterRcsOnlyFromImsRegistration() throws Exception {
+ DeviceCapabilityListener deviceCapListener = createDeviceCapabilityListener();
+ deviceCapListener.setImsCallbackRegistered(true);
+ Handler handler = deviceCapListener.getHandler();
+
+ // set the Ims is registered
+ doReturn(true).when(mDeviceCapability).isImsRegistered();
+ ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_NOT_REGISTERED, -1, "");
+ // RCS unregistered
+ RegistrationCallback rcsRegiCallback = deviceCapListener.mRcsRegistrationCallback;
+
+ doReturn(true).when(mDeviceCapability).updateImsRcsUnregistered();
+ // RCS is unregistered but MMTEL is registered.
+ doReturn(true).when(mDeviceCapability).isImsRegistered();
+ rcsRegiCallback.onUnregistered(info);
+
+ waitForHandlerActionDelayed(handler, HANDLER_WAIT_TIMEOUT_MS, HANDLER_SENT_DELAY_MS);
+
+ verify(mDeviceCapability).updateImsRcsUnregistered();
+ // Only RCS unregistered. Verify the request of the modify publish is sent.
+ verify(mCallback).requestPublishFromInternal(
+ PublishController.PUBLISH_TRIGGER_RCS_URI_CHANGE);
+
+ // Only RCS unregistered. Verify do not send ImsUnregistered.
+ verify(mCallback, never()).updateImsUnregistered();
+ }
+
private DeviceCapabilityListener createDeviceCapabilityListener() {
DeviceCapabilityListener deviceCapListener = new DeviceCapabilityListener(mContext,
mSubId, mDeviceCapability, mCallback, mUceStatsWriter);
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 a7e0bbbe..aa145c7c 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
@@ -22,6 +22,8 @@ import static com.android.ims.rcs.uce.presence.publish.PublishController.PUBLISH
import static junit.framework.Assert.assertFalse;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -34,6 +36,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.RemoteCallbackList;
import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IRcsUcePublishStateCallback;
import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
@@ -137,7 +140,7 @@ public class PublishControllerImplTest extends ImsTestBase {
assertEquals(RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED, initState);
publishController.getPublishControllerCallback().updatePublishRequestResult(
- RcsUceAdapter.PUBLISH_STATE_OK, Instant.now(), null);
+ RcsUceAdapter.PUBLISH_STATE_OK, Instant.now(), null, null);
Handler handler = publishController.getPublishHandler();
waitForHandlerAction(handler, 1000);
@@ -154,7 +157,7 @@ public class PublishControllerImplTest extends ImsTestBase {
assertEquals(RcsUceAdapter.PUBLISH_STATE_NOT_PUBLISHED, initState);
publishController.getPublishControllerCallback().updatePublishRequestResult(
- RcsUceAdapter.PUBLISH_STATE_PUBLISHING, Instant.now(), null);
+ RcsUceAdapter.PUBLISH_STATE_PUBLISHING, Instant.now(), null, null);
Handler handler = publishController.getPublishHandler();
waitForHandlerAction(handler, 1000);
@@ -223,8 +226,10 @@ public class PublishControllerImplTest extends ImsTestBase {
public void testPublishUpdated() throws Exception {
PublishControllerImpl publishController = createPublishController();
int responseCode = 200;
+ String responsePhrase = "OK";
- publishController.onPublishUpdated(responseCode, "", 0, "");
+ publishController.onPublishUpdated(new SipDetails.Builder(SipDetails.METHOD_PUBLISH)
+ .setSipResponseCode(responseCode, responsePhrase).build());
Handler handler = publishController.getPublishHandler();
waitForHandlerAction(handler, 1000);
@@ -235,14 +240,64 @@ public class PublishControllerImplTest extends ImsTestBase {
verify(mPublishProcessor).publishUpdated(captor.capture());
PublishRequestResponse response = captor.getValue();
int expectedCode = response.getNetworkRespSipCode().orElse(-1);
+ String expectedPhrase = response.getReasonPhrase().orElse("");
assertEquals(responseCode, expectedCode);
+ assertEquals(responsePhrase, expectedPhrase);
+ SipDetails details = response.getSipDetails().orElse(null);
+ assertNotNull(details);
+ assertEquals(responseCode, details.getResponseCode());
+ assertEquals(responsePhrase, details.getResponsePhrase());
+ }
+
+ @Test
+ @SmallTest
+ public void testPublishUpdatedWithSipDetails() throws Exception {
+ PublishControllerImpl publishController = createPublishController();
+ int responseCode = 200;
+ String responsePhrase = "OK";
+ int reasonHdrCause = 7;
+ String reasonHdrText = "reasonHeaderText";
+ int cseq = 10;
+ String callId = "TestCallId";
+
+ publishController.onPublishUpdated(new SipDetails.Builder(SipDetails.METHOD_PUBLISH)
+ .setCSeq(cseq).setSipResponseCode(responseCode, responsePhrase).setCallId(callId)
+ .setSipResponseReasonHeader(reasonHdrCause, reasonHdrText).build());
+
+ Handler handler = publishController.getPublishHandler();
+ waitForHandlerAction(handler, 1000);
+
+ ArgumentCaptor<PublishRequestResponse> captor =
+ ArgumentCaptor.forClass(PublishRequestResponse.class);
+
+ verify(mPublishProcessor).publishUpdated(captor.capture());
+ PublishRequestResponse response = captor.getValue();
+ int expectedCode = response.getNetworkRespSipCode().orElse(-1);
+ String expectedPhrase = response.getReasonPhrase().orElse("");
+ int expectedReasonCause = response.getReasonHeaderCause().orElse(-1);
+ String expectedReasonText = response.getReasonHeaderText().orElse("");
+
+ assertEquals(responseCode, expectedCode);
+ assertEquals(responsePhrase, expectedPhrase);
+ assertEquals(reasonHdrCause, expectedReasonCause);
+ assertEquals(reasonHdrText, expectedReasonText);
+
+ SipDetails details = response.getSipDetails().orElse(null);
+ assertNotNull(details);
+ assertEquals(SipDetails.METHOD_PUBLISH, details.getMethod());
+ assertEquals(cseq, details.getCSeq());
+ assertEquals(responseCode, details.getResponseCode());
+ assertEquals(responsePhrase, details.getResponsePhrase());
+ assertEquals(reasonHdrCause, details.getReasonHeaderCause());
+ assertEquals(reasonHdrText, details.getReasonHeaderText());
+ assertEquals(callId, details.getCallId());
}
@Test
@SmallTest
public void testPublishingStateTargetingEnable() throws Exception {
doReturn(1).when(mPublishStateCallbacks).getRegisteredCallbackCount();
- Boolean boolObj = new Boolean(true);
+ Boolean boolObj = Boolean.TRUE;
Object uid1 = (Object)boolObj;
doReturn(uid1).when(mPublishStateCallbacks).getRegisteredCallbackCookie(anyInt());
@@ -282,7 +337,7 @@ public class PublishControllerImplTest extends ImsTestBase {
@SmallTest
public void testPublishingStateTargetingDisable() throws Exception {
doReturn(1).when(mPublishStateCallbacks).getRegisteredCallbackCount();
- Boolean boolObj = new Boolean(false);
+ Boolean boolObj = Boolean.FALSE;
Object uid1 = (Object)boolObj;
doReturn(uid1).when(mPublishStateCallbacks).getRegisteredCallbackCookie(anyInt());
diff --git a/tests/src/com/android/ims/rcs/uce/presence/publish/PublishProcessorTest.java b/tests/src/com/android/ims/rcs/uce/presence/publish/PublishProcessorTest.java
index 4e8cdfdc..2de47146 100644
--- a/tests/src/com/android/ims/rcs/uce/presence/publish/PublishProcessorTest.java
+++ b/tests/src/com/android/ims/rcs/uce/presence/publish/PublishProcessorTest.java
@@ -30,6 +30,7 @@ import android.content.Context;
import android.net.Uri;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.SipDetails;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -82,6 +83,7 @@ public class PublishProcessorTest extends ImsTestBase {
doReturn(true).when(mDeviceCapabilities).isImsRegistered();
RcsContactUceCapability capability = getRcsContactUceCapability();
+ doReturn(capability).when(mDeviceCapabilities).getChangedPresenceCapability(any());
doReturn(capability).when(mDeviceCapabilities).getDeviceCapabilities(anyInt(), any());
doReturn(mTaskId).when(mResponseCallback).getTaskId();
@@ -112,7 +114,7 @@ public class PublishProcessorTest extends ImsTestBase {
PublishProcessor publishProcessor = getPublishProcessor();
publishProcessor.doPublish(PublishController.PUBLISH_TRIGGER_RETRY);
-
+ verify(mDeviceCapabilities).getChangedPresenceCapability(any());
verify(mProcessorState, never()).resetRetryCount();
}
@@ -139,7 +141,7 @@ public class PublishProcessorTest extends ImsTestBase {
publishProcessor.onNetworkResponse(mResponseCallback);
- verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());
+ verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(), eq(null));
verify(mResponseCallback).onDestroy();
verify(mProcessorState).setPublishingFlag(false);
verify(mPublishCtrlCallback).clearRequestCanceledTimer();
@@ -171,6 +173,7 @@ public class PublishProcessorTest extends ImsTestBase {
publishProcessor.onCommandError(mResponseCallback);
+ verify(mDeviceCapabilities).setPresencePublishResult(false);
verify(mProcessorState).increaseRetryCount();
verify(mPublishCtrlCallback).requestPublishFromInternal(
eq(PublishController.PUBLISH_TRIGGER_RETRY));
@@ -188,11 +191,13 @@ public class PublishProcessorTest extends ImsTestBase {
doReturn(mTaskId).when(mProcessorState).getCurrentTaskId();
doReturn(mTaskId).when(mResponseCallback).getTaskId();
doReturn(false).when(mResponseCallback).needRetry();
+ doReturn(true).when(mResponseCallback).isRequestSuccess();
PublishProcessor publishProcessor = getPublishProcessor();
publishProcessor.onCommandError(mResponseCallback);
- verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());
+ verify(mDeviceCapabilities).setPresencePublishResult(true);
+ verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(), eq(null));
verify(mResponseCallback).onDestroy();
verify(mProcessorState).setPublishingFlag(false);
verify(mPublishCtrlCallback).clearRequestCanceledTimer();
@@ -209,6 +214,7 @@ public class PublishProcessorTest extends ImsTestBase {
publishProcessor.onNetworkResponse(mResponseCallback);
+ verify(mDeviceCapabilities).setPresencePublishResult(false);
verify(mProcessorState).increaseRetryCount();
verify(mPublishCtrlCallback).requestPublishFromInternal(
eq(PublishController.PUBLISH_TRIGGER_RETRY));
@@ -226,11 +232,20 @@ public class PublishProcessorTest extends ImsTestBase {
doReturn(false).when(mResponseCallback).needRetry();
doReturn(true).when(mResponseCallback).isRequestSuccess();
doReturn(Optional.of(200)).when(mResponseCallback).getNetworkRespSipCode();
+
+ SipDetails details = new SipDetails.Builder(SipDetails.METHOD_PUBLISH)
+ .setCSeq(10).setSipResponseCode(200, "OK").setCallId("CallId").build();
+ Optional<SipDetails> sipDetails = Optional.ofNullable(details);
+ doReturn(sipDetails).when(mResponseCallback).getSipDetails();
+
PublishProcessor publishProcessor = getPublishProcessor();
publishProcessor.onNetworkResponse(mResponseCallback);
+ SipDetails actualInfo = sipDetails.orElse(null);
- verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());
+ verify(mDeviceCapabilities).setPresencePublishResult(true);
+ verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(),
+ eq(actualInfo));
verify(mResponseCallback).onDestroy();
verify(mProcessorState).setPublishingFlag(false);
verify(mPublishCtrlCallback).clearRequestCanceledTimer();
@@ -260,13 +275,21 @@ public class PublishProcessorTest extends ImsTestBase {
doReturn(0).when(mResponseCallback).getPublishState();
doReturn("").when(mResponseCallback).getPidfXml();
+ SipDetails details = new SipDetails.Builder(SipDetails.METHOD_PUBLISH)
+ .setCSeq(10).setSipResponseCode(200, "").setCallId("CallId").build();
+ Optional<SipDetails> sipDetails = Optional.ofNullable(details);
+ doReturn(sipDetails).when(mResponseCallback).getSipDetails();
+
PublishProcessor publishProcessor = getPublishProcessor();
publishProcessor.publishUpdated(mResponseCallback);
+ SipDetails actualInfo = sipDetails.orElse(null);
+ verify(mDeviceCapabilities).setPresencePublishResult(true);
verify(mProcessorState).setLastPublishedTime(any());
verify(mProcessorState).resetRetryCount();
- verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any());
+ verify(mPublishCtrlCallback).updatePublishRequestResult(anyInt(), any(), any(),
+ eq(actualInfo));
}
private PublishProcessor getPublishProcessor() {
diff --git a/tests/src/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTrackerTest.java b/tests/src/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTrackerTest.java
index 55006299..52017c7a 100644
--- a/tests/src/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTrackerTest.java
+++ b/tests/src/com/android/ims/rcs/uce/presence/publish/PublishServiceDescTrackerTest.java
@@ -107,7 +107,6 @@ public class PublishServiceDescTrackerTest {
t1.updateImsRegistration(imsReg);
assertEquals(expectedSet, t1.copyRegistrationCapabilities());
-
expectedSet = Collections.singleton(
ServiceDescription.SERVICE_DESCRIPTION_CHATBOT_SESSION);
imsReg = createImsRegistration(
@@ -139,6 +138,30 @@ public class PublishServiceDescTrackerTest {
FeatureTags.FEATURE_TAG_VIDEO);
t1.updateImsRegistration(imsReg);
assertEquals(expectedSet, t1.copyRegistrationCapabilities());
+
+ expectedSet = Collections.singleton(
+ ServiceDescription.SERVICE_DESCRIPTION_SLM);
+ imsReg = createImsRegistration(
+ FeatureTags.FEATURE_TAG_PAGER_MODE,
+ FeatureTags.FEATURE_TAG_LARGE_MODE,
+ FeatureTags.FEATURE_TAG_DEFERRED_MESSAGING,
+ FeatureTags.FEATURE_TAG_LARGE_PAGER_MODE);
+ t1.updateImsRegistration(imsReg);
+ assertEquals(expectedSet, t1.copyRegistrationCapabilities());
+
+
+ expectedSet = Collections.singleton(
+ ServiceDescription.SERVICE_DESCRIPTION_SLM_PAGER_LARGE);
+ imsReg = createImsRegistration(
+ FeatureTags.FEATURE_TAG_PAGER_MODE,
+ FeatureTags.FEATURE_TAG_LARGE_MODE);
+ t1.updateImsRegistration(imsReg);
+ assertEquals(expectedSet, t1.copyRegistrationCapabilities());
+
+ // delete the feature tags for Unregistered
+ expectedSet = new ArraySet<>();
+ t1.updateImsRegistration(Collections.emptySet());
+ assertEquals(expectedSet, t1.copyRegistrationCapabilities());
}
@SmallTest
diff --git a/tests/src/com/android/ims/rcs/uce/request/SubscribeCoordinatorTest.java b/tests/src/com/android/ims/rcs/uce/request/SubscribeCoordinatorTest.java
index bcd3c98d..2c0042ea 100644
--- a/tests/src/com/android/ims/rcs/uce/request/SubscribeCoordinatorTest.java
+++ b/tests/src/com/android/ims/rcs/uce/request/SubscribeCoordinatorTest.java
@@ -25,14 +25,11 @@ import static com.android.ims.rcs.uce.request.UceRequestCoordinator.REQUEST_UPDA
import static com.android.ims.rcs.uce.request.UceRequestCoordinator.REQUEST_UPDATE_RESOURCE_TERMINATED;
import static com.android.ims.rcs.uce.request.UceRequestCoordinator.REQUEST_UPDATE_TERMINATED;
-import static java.lang.Boolean.TRUE;
-
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
@@ -41,6 +38,7 @@ import static org.mockito.Mockito.verify;
import android.net.Uri;
import android.telephony.ims.RcsContactPresenceTuple;
import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.IRcsUceControllerCallback;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -49,21 +47,23 @@ import androidx.test.filters.SmallTest;
import com.android.ims.ImsTestBase;
import com.android.ims.rcs.uce.UceDeviceState.DeviceStateResult;
import com.android.ims.rcs.uce.UceStatsWriter;
+import com.android.ims.rcs.uce.eab.EabCapabilityResult;
import com.android.ims.rcs.uce.request.UceRequestCoordinator.RequestResult;
import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+
@RunWith(AndroidJUnit4.class)
public class SubscribeCoordinatorTest extends ImsTestBase {
@@ -127,6 +127,17 @@ public class SubscribeCoordinatorTest extends ImsTestBase {
@Test
@SmallTest
public void testRequestNetworkRespSuccess() throws Exception {
+ int responseCode = 200;
+ String responsePhrase = "OK";
+ int reasonHdrCause = 1;
+ String reasonHdrText = "reasonText";
+ int cSeq = 10;
+ String callId = "TestCallId";
+ SipDetails details = new SipDetails.Builder(SipDetails.METHOD_SUBSCRIBE).setCSeq(cSeq)
+ .setSipResponseCode(responseCode, responsePhrase).setCallId(callId)
+ .setSipResponseReasonHeader(reasonHdrCause, reasonHdrText).build();
+ doReturn(Optional.ofNullable(details)).when(mResponse).getSipDetails();
+
SubscribeRequestCoordinator coordinator = getSubscribeCoordinator();
doReturn(true).when(mResponse).isNetworkResponseOK();
doReturn(Optional.of(200)).when(mResponse).getNetworkRespSipCode();
@@ -138,8 +149,21 @@ public class SubscribeCoordinatorTest extends ImsTestBase {
assertEquals(1, requestList.size());
assertTrue(resultList.isEmpty());
- verify(mUceStatsWriter).setSubscribeResponse(eq(mSubId), eq(mTaskId), eq(200));
+ Iterator<RequestResult> requestResults = resultList.iterator();
+ while (requestResults.hasNext()) {
+ RequestResult req = requestResults.next();
+ SipDetails receivedInfo = req.getSipDetails().orElse(null);
+ assertNotNull(receivedInfo);
+ assertEquals(SipDetails.METHOD_SUBSCRIBE, receivedInfo.getMethod());
+ assertEquals(cSeq, receivedInfo.getCSeq());
+ assertEquals(responseCode, receivedInfo.getResponseCode());
+ assertEquals(responsePhrase, receivedInfo.getResponsePhrase());
+ assertEquals(reasonHdrCause, receivedInfo.getReasonHeaderCause());
+ assertEquals(reasonHdrText, receivedInfo.getReasonHeaderText());
+ assertEquals(callId, receivedInfo.getCallId());
+ }
+ verify(mUceStatsWriter).setSubscribeResponse(eq(mSubId), eq(mTaskId), eq(200));
verify(mRequest, never()).onFinish();
}
@@ -150,10 +174,20 @@ public class SubscribeCoordinatorTest extends ImsTestBase {
SubscribeRequestCoordinator coordinator = getSubscribeCoordinator();
+ List<EabCapabilityResult> eabResultList = new ArrayList<>();
+
+ Uri contactUri = Uri.fromParts("tel", "123456789", null);
+ EabCapabilityResult result = new EabCapabilityResult(contactUri,
+ EabCapabilityResult.EAB_CONTACT_NOT_FOUND_FAILURE, null);
+ eabResultList.add(result);
+
+ doReturn(eabResultList).when(mRequestMgrCallback).
+ getCapabilitiesFromCacheIncludingExpired(any());
+
coordinator.onRequestUpdated(mTaskId, REQUEST_UPDATE_NETWORK_RESPONSE);
verify(mUceStatsWriter).setSubscribeResponse(eq(mSubId), eq(mTaskId), eq(400));
-
+ verify(mRequestMgrCallback, never()).saveCapabilities(any());
verify(mRequest).onFinish();
}
diff --git a/tests/src/com/android/ims/rcs/uce/request/SubscribeRequestTest.java b/tests/src/com/android/ims/rcs/uce/request/SubscribeRequestTest.java
index b4f9cca4..543ad6d2 100644
--- a/tests/src/com/android/ims/rcs/uce/request/SubscribeRequestTest.java
+++ b/tests/src/com/android/ims/rcs/uce/request/SubscribeRequestTest.java
@@ -19,7 +19,9 @@ package com.android.ims.rcs.uce.request;
import static android.telephony.ims.stub.RcsCapabilityExchangeImplBase.COMMAND_CODE_NOT_SUPPORTED;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
@@ -28,6 +30,7 @@ import static org.mockito.Mockito.verify;
import android.net.Uri;
import android.telephony.ims.RcsContactTerminatedReason;
import android.telephony.ims.RcsUceAdapter;
+import android.telephony.ims.SipDetails;
import android.telephony.ims.aidl.ISubscribeResponseCallback;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -36,10 +39,6 @@ import androidx.test.filters.SmallTest;
import com.android.ims.ImsTestBase;
import com.android.ims.rcs.uce.presence.subscribe.SubscribeController;
import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
-import com.android.ims.rcs.uce.util.NetworkSipCode;
-
-import java.util.ArrayList;
-import java.util.List;
import org.junit.After;
import org.junit.Before;
@@ -47,6 +46,9 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(AndroidJUnit4.class)
public class SubscribeRequestTest extends ImsTestBase {
@@ -88,6 +90,7 @@ public class SubscribeRequestTest extends ImsTestBase {
subscribeRequest.requestCapabilities(uriList);
verify(mRequestResponse).setRequestInternalError(RcsUceAdapter.ERROR_GENERIC_FAILURE);
+ verify(mRequestResponse, never()).setSipDetails(any());
verify(mRequestManagerCallback).notifyRequestError(eq(mCoordId), anyLong());
verify(mSubscribeController, never()).requestCapabilities(any(), any());
}
@@ -101,6 +104,7 @@ public class SubscribeRequestTest extends ImsTestBase {
callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
verify(mRequestResponse).setCommandError(COMMAND_CODE_NOT_SUPPORTED);
+ verify(mRequestResponse, never()).setSipDetails(any(SipDetails.class));
verify(mRequestManagerCallback).notifyCommandError(eq(mCoordId), anyLong());
}
@@ -109,12 +113,16 @@ public class SubscribeRequestTest extends ImsTestBase {
public void testNetworkResponse() throws Exception {
SubscribeRequest subscribeRequest = getSubscribeRequest();
- int sipCode = NetworkSipCode.SIP_CODE_FORBIDDEN;
- String reason = "forbidden";
+ int sipCode = 200;
+ String reason = "OK";
+ SipDetails details = new SipDetails.Builder(SipDetails.METHOD_SUBSCRIBE).setCSeq(1)
+ .setSipResponseCode(sipCode, reason).setCallId("callId").build();
+
ISubscribeResponseCallback callback = subscribeRequest.getResponseCallback();
- callback.onNetworkResponse(sipCode, reason);
+ callback.onNetworkResponse(details);
- verify(mRequestResponse).setNetworkResponseCode(sipCode, reason);
+ verify(mRequestResponse).setSipDetails(eq(details));
+ verify(mRequestResponse, never()).setNetworkResponseCode(anyInt(), anyString());
verify(mRequestManagerCallback).notifyNetworkResponse(eq(mCoordId), anyLong());
}
@@ -130,6 +138,7 @@ public class SubscribeRequestTest extends ImsTestBase {
callback.onResourceTerminated(list);
verify(mRequestResponse).addTerminatedResource(list);
+ verify(mRequestResponse, never()).setSipDetails(any());
verify(mRequestManagerCallback).notifyResourceTerminated(eq(mCoordId), anyLong());
}
@@ -144,6 +153,7 @@ public class SubscribeRequestTest extends ImsTestBase {
callback.onNotifyCapabilitiesUpdate(pidfXml);
verify(mRequestResponse).addUpdatedCapabilities(any());
+ verify(mRequestResponse, never()).setSipDetails(any());
verify(mRequestManagerCallback).notifyCapabilitiesUpdated(eq(mCoordId), anyLong());
}
@@ -159,6 +169,7 @@ public class SubscribeRequestTest extends ImsTestBase {
callback.onTerminated(reason, retryAfterMillis);
verify(mRequestResponse).setTerminated(reason, retryAfterMillis);
+ verify(mRequestResponse, never()).setSipDetails(any());
verify(mRequestManagerCallback).notifyTerminated(eq(mCoordId), anyLong());
}
diff --git a/tests/src/com/android/ims/rcs/uce/request/UceRequestManagerTest.java b/tests/src/com/android/ims/rcs/uce/request/UceRequestManagerTest.java
index b380eac9..fa8214ed 100644
--- a/tests/src/com/android/ims/rcs/uce/request/UceRequestManagerTest.java
+++ b/tests/src/com/android/ims/rcs/uce/request/UceRequestManagerTest.java
@@ -31,6 +31,7 @@ import static com.android.ims.rcs.uce.request.UceRequestCoordinator.REQUEST_UPDA
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -133,7 +134,7 @@ public class UceRequestManagerTest extends ImsTestBase {
waitForHandlerAction(handler, 500L);
verify(mUceRequest, never()).executeRequest();
- verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L);
+ verify(mCapabilitiesCallback).onError(RcsUceAdapter.ERROR_GENERIC_FAILURE, 0L, null);
}
/**
@@ -164,7 +165,7 @@ public class UceRequestManagerTest extends ImsTestBase {
verify(mCapabilitiesCallback).onCapabilitiesReceived(
cachedNumbers.stream().map(EabCapabilityResult::getContactCapabilities).collect(
Collectors.toList()));
- verify(mCapabilitiesCallback).onComplete();
+ verify(mCapabilitiesCallback).onComplete(eq(null));
// The cache should have been hit, so no network requests should have been generated.
verify(mRequestRepository, never()).addRequestCoordinator(any());
}
@@ -196,7 +197,7 @@ public class UceRequestManagerTest extends ImsTestBase {
waitForHandlerAction(handler, 500L);
// Extract caps from EabCapabilityResult and ensure the Lists match.
verify(mCapabilitiesCallback, never()).onCapabilitiesReceived(any());
- verify(mCapabilitiesCallback, never()).onComplete();
+ verify(mCapabilitiesCallback, never()).onComplete(any());
// A network request should have been generated for the expired contact.
verify(mRequestRepository).addRequestCoordinator(any());
}
@@ -240,7 +241,7 @@ public class UceRequestManagerTest extends ImsTestBase {
// Extract caps from EabCapabilityResult and ensure the Lists match.
verify(mCapabilitiesCallback).onCapabilitiesReceived(
Collections.singletonList(cachedItem.getContactCapabilities()));
- verify(mCapabilitiesCallback, never()).onComplete();
+ verify(mCapabilitiesCallback, never()).onComplete(any());
// The cache should have been hit, but there was also entry that was not in the cache, so
// ensure that is requested.
verify(mRequestRepository).addRequestCoordinator(any());