When receiving the empty pidf xml data, treat the contacts as a non-RCS user am: b2f1e2cc3b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/opt/net/ims/+/14999353

Change-Id: Ib8cf5dd356ae61d10c88b65ed4e7670a19d7abd5
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 1ac46a7..97371b8 100644
--- a/src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java
+++ b/src/java/com/android/ims/rcs/uce/request/CapabilityRequestResponse.java
@@ -23,6 +23,7 @@
 import android.telephony.ims.RcsUceAdapter.ErrorCode;
 import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
 import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.CommandCode;
+import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.ims.rcs.uce.UceController;
@@ -82,7 +83,7 @@
     private Set<String> mRemoteCaps;
 
     // The collection to record whether the request contacts have received the capabilities updated.
-    private Map<String, Boolean> mContactCapsReceived;
+    private Map<Uri, Boolean> mContactCapsReceived;
 
     public CapabilityRequestResponse() {
         mRequestInternalError = Optional.empty();
@@ -104,19 +105,24 @@
      * Set the request contacts which is expected to receive the capabilities updated.
      */
     public synchronized void setRequestContacts(List<Uri> contactUris) {
-        // Convert the given contact uris to the contact numbers.
-        List<String> numbers = contactUris.stream()
-                .map(UceUtils::getContactNumber)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toList());
-
         // Initialize the default value to FALSE. All the numbers have not received the
         // capabilities updated.
-        numbers.stream().forEach(contact -> mContactCapsReceived.put(contact, Boolean.FALSE));
+        contactUris.forEach(contact -> mContactCapsReceived.put(contact, Boolean.FALSE));
         Log.d(LOG_TAG, "setRequestContacts: size=" + mContactCapsReceived.size());
     }
 
     /**
+     * Get the contacts that have not received the capabilities updated yet.
+     */
+    public synchronized List<Uri> getNotReceiveCapabilityUpdatedContact() {
+        return mContactCapsReceived.entrySet()
+                .stream()
+                .filter(entry -> Objects.equals(entry.getValue(), Boolean.FALSE))
+                .map(Map.Entry::getKey)
+                .collect(Collectors.toList());
+    }
+
+    /**
      * Set the request contacts which is expected to receive the capabilities updated.
      */
     public synchronized boolean haveAllRequestCapsUpdatedBeenReceived() {
@@ -251,8 +257,9 @@
             if (updatedUri == null) continue;
             String updatedUriStr = updatedUri.toString();
 
-            for (Map.Entry<String, Boolean> contactCapEntry : mContactCapsReceived.entrySet()) {
-                if (updatedUriStr.contains(contactCapEntry.getKey())) {
+            for (Map.Entry<Uri, Boolean> contactCapEntry : mContactCapsReceived.entrySet()) {
+                String number = UceUtils.getContactNumber(contactCapEntry.getKey());
+                if (!TextUtils.isEmpty(number) && updatedUriStr.contains(number)) {
                     // Set the flag that this contact has received the capability updated.
                     contactCapEntry.setValue(true);
                 }
@@ -380,17 +387,24 @@
 
     /**
      * Check the contacts of the request is not found.
-     * @return true if the sip code of the network response is NOT_FOUND(404) or
-     * DOES_NOT_EXIST_ANYWHERE(604)
+     * @return true if the sip code of the network response is one of NOT_FOUND(404),
+     * SIP_CODE_METHOD_NOT_ALLOWED(405) or DOES_NOT_EXIST_ANYWHERE(604)
      */
     public synchronized boolean isNotFound() {
-        final int notFound = NetworkSipCode.SIP_CODE_NOT_FOUND;
-        final int notExistAnywhere = NetworkSipCode.SIP_CODE_DOES_NOT_EXIST_ANYWHERE;
-        Optional<Integer> reasonHeaderCause = getReasonHeaderCause();
-        Optional<Integer> respSipCode = getNetworkRespSipCode();
-        if (reasonHeaderCause.filter(c -> c == notFound || c == notExistAnywhere).isPresent() ||
-                respSipCode.filter(c -> c == notFound || c == notExistAnywhere).isPresent()) {
-            return true;
+        Optional<Integer> respSipCode = Optional.empty();
+        if (getReasonHeaderCause().isPresent()) {
+            respSipCode = getReasonHeaderCause();
+        } else if (getNetworkRespSipCode().isPresent()) {
+            respSipCode = getNetworkRespSipCode();
+        }
+
+        if (respSipCode.isPresent()) {
+            int sipCode = respSipCode.get();
+            if (sipCode == NetworkSipCode.SIP_CODE_NOT_FOUND ||
+            sipCode == NetworkSipCode.SIP_CODE_METHOD_NOT_ALLOWED ||
+            sipCode == NetworkSipCode.SIP_CODE_DOES_NOT_EXIST_ANYWHERE) {
+                return true;
+            }
         }
         return false;
     }
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 eb36839..2b5e91a 100644
--- a/src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java
+++ b/src/java/com/android/ims/rcs/uce/request/SubscribeRequest.java
@@ -26,6 +26,7 @@
 import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.CommandCode;
 
 import com.android.ims.rcs.uce.presence.pidfparser.PidfParser;
+import com.android.ims.rcs.uce.presence.pidfparser.PidfParserUtils;
 import com.android.ims.rcs.uce.presence.subscribe.SubscribeController;
 import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
 import com.android.internal.annotations.VisibleForTesting;
@@ -194,6 +195,18 @@
                 .filter(Objects::nonNull)
                 .collect(Collectors.toList());
 
+        // When the given PIDF xml is empty, set the contacts who have not received the
+        // capabilities updated as non-RCS user.
+        if (capabilityList.isEmpty()) {
+            logd("onCapabilitiesUpdate: The capabilities list is empty, Set to non-RCS user.");
+            List<Uri> notReceiveCapUpdatedContactList =
+                    mRequestResponse.getNotReceiveCapabilityUpdatedContact();
+            capabilityList = notReceiveCapUpdatedContactList.stream()
+                    .map(PidfParserUtils::getNotFoundContactCapabilities)
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
+        }
+
         logd("onCapabilitiesUpdate: PIDF size=" + pidfXml.size()
                 + ", contact capability size=" + capabilityList.size());
 
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 54aa5cc..ee6bd35 100644
--- a/src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java
+++ b/src/java/com/android/ims/rcs/uce/request/SubscribeRequestCoordinator.java
@@ -113,6 +113,11 @@
         }
     };
 
+    // 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);
+
     // The RequestResult creator of the request terminated.
     private static final RequestResultCreator sTerminatedCreator = (taskId, response,
             requestMgrCallback) -> {
@@ -266,12 +271,9 @@
         // request. Check the forbidden state and finish this request. Otherwise, keep waiting for
         // the subsequent callback of this request.
         if (!response.isNetworkResponseOK()) {
-            Long taskId = request.getTaskId();
-            RequestResult requestResult = sNetworkRespErrorCreator.createRequestResult(taskId,
-                    response, mRequestManagerCallback);
-
-            // handle forbidden and not found case.
-            handleNetworkResponseFailed(request, requestResult);
+            // Handle the network response not OK cases and get the request result to finish this
+            // request.
+            RequestResult requestResult = handleNetworkResponseFailed(request);
 
             // Trigger capabilities updated callback if there is any.
             List<RcsContactUceCapability> updatedCapList = response.getUpdatedContactCapability();
@@ -285,20 +287,36 @@
             request.onFinish();
 
             // Remove this request from the activated collection and notify RequestManager.
-            moveRequestToFinishedCollection(taskId, requestResult);
+            moveRequestToFinishedCollection(request.getTaskId(), requestResult);
         }
     }
 
-    private void handleNetworkResponseFailed(SubscribeRequest request, RequestResult result) {
-        CapabilityRequestResponse response = request.getRequestResponse();
+    private RequestResult handleNetworkResponseFailed(SubscribeRequest request) {
+        final long taskId = request.getTaskId();
+        final CapabilityRequestResponse response = request.getRequestResponse();
+        RequestResult requestResult = null;
 
         if (response.isNotFound()) {
+            // In the network response with the not found case, we won't receive the capabilities
+            // updated callback from the ImsService afterward. Therefore, we create the capabilities
+            // with the result REQUEST_RESULT_NOT_FOUND by ourself and will trigger the
+            // capabilities received callback to the clients later.
             List<Uri> uriList = request.getContactUri();
             List<RcsContactUceCapability> capabilityList = uriList.stream().map(uri ->
                     PidfParserUtils.getNotFoundContactCapabilities(uri))
                     .collect(Collectors.toList());
             response.addUpdatedCapabilities(capabilityList);
+
+            // We treat the NOT FOUND is a successful result.
+            requestResult = sNetworkRespSuccessfulCreator.createRequestResult(taskId, response,
+                    mRequestManagerCallback);
         }
+
+        if (requestResult == null) {
+            requestResult = sNetworkRespErrorCreator.createRequestResult(taskId, response,
+                    mRequestManagerCallback);
+        }
+        return requestResult;
     }
 
     /**
diff --git a/src/java/com/android/ims/rcs/uce/util/NetworkSipCode.java b/src/java/com/android/ims/rcs/uce/util/NetworkSipCode.java
index 3789903..a1e35d7 100644
--- a/src/java/com/android/ims/rcs/uce/util/NetworkSipCode.java
+++ b/src/java/com/android/ims/rcs/uce/util/NetworkSipCode.java
@@ -30,6 +30,7 @@
     public static final int SIP_CODE_BAD_REQUEST = 400;
     public static final int SIP_CODE_FORBIDDEN = 403;
     public static final int SIP_CODE_NOT_FOUND = 404;
+    public static final int SIP_CODE_METHOD_NOT_ALLOWED = 405;
     public static final int SIP_CODE_REQUEST_TIMEOUT = 408;
     public static final int SIP_CODE_INTERVAL_TOO_BRIEF = 423;
     public static final int SIP_CODE_TEMPORARILY_UNAVAILABLE = 480;