diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 07dec52acbf3478c91a758edd68c81beacafcfd5..06d7f2495978a5ce6abec7cc9935146bc1c119c3 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -12257,10 +12257,16 @@ package android.telephony.ims.feature {
 package android.telephony.ims.stub {
 
   public interface CapabilityExchangeEventListener {
+    method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException;
     method public void onRequestPublishCapabilities(int) throws android.telephony.ims.ImsException;
     method public void onUnpublish() throws android.telephony.ims.ImsException;
   }
 
+  public static interface CapabilityExchangeEventListener.OptionsRequestCallback {
+    method public default void onRespondToCapabilityRequest(@NonNull android.telephony.ims.RcsContactUceCapability, boolean);
+    method public void onRespondToCapabilityRequestWithError(@IntRange(from=100, to=699) int, @NonNull String);
+  }
+
   public interface DelegateConnectionMessageCallback {
     method public void onMessageReceived(@NonNull android.telephony.ims.SipMessage);
     method public void onMessageSendFailure(@NonNull String, int);
@@ -12446,6 +12452,7 @@ package android.telephony.ims.stub {
   public class RcsCapabilityExchangeImplBase {
     ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor);
     method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback);
+    method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback);
     method public void subscribeForCapabilities(@NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback);
     field public static final int COMMAND_CODE_FETCH_ERROR = 3; // 0x3
     field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1
@@ -12460,6 +12467,11 @@ package android.telephony.ims.stub {
     field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0
   }
 
+  public static interface RcsCapabilityExchangeImplBase.OptionsResponseCallback {
+    method public void onCommandError(int) throws android.telephony.ims.ImsException;
+    method public void onNetworkResponse(int, @NonNull String, @NonNull java.util.List<java.lang.String>) throws android.telephony.ims.ImsException;
+  }
+
   public static interface RcsCapabilityExchangeImplBase.PublishResponseCallback {
     method public void onCommandError(int) throws android.telephony.ims.ImsException;
     method public void onNetworkResponse(@IntRange(from=100, to=699) int, @NonNull String) throws android.telephony.ims.ImsException;
diff --git a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
index 4435640e008cd1a2e9bab386ce097f9d4e8600d2..a217d13213427093eab6c59479a0ca3078d947f1 100644
--- a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.RemoteException;
+import android.telephony.ims.ImsException;
 import android.telephony.ims.RcsContactUceCapability;
 import android.telephony.ims.stub.CapabilityExchangeEventListener;
 import android.util.Log;
@@ -47,7 +48,7 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
      * Receives the request of publishing capabilities from the network and deliver this request
      * to the framework via the registered capability exchange event listener.
      */
-    public void onRequestPublishCapabilities(int publishTriggerType) {
+    public void onRequestPublishCapabilities(int publishTriggerType) throws ImsException {
         ICapabilityExchangeEventListener listener = mListenerBinder;
         if (listener == null) {
             return;
@@ -56,13 +57,15 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
             listener.onRequestPublishCapabilities(publishTriggerType);
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "request publish capabilities exception: " + e);
+            throw new ImsException("Remote is not available",
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
     /**
      * Receives the unpublish notification and deliver this callback to the framework.
      */
-    public void onUnpublish() {
+    public void onUnpublish() throws ImsException {
         ICapabilityExchangeEventListener listener = mListenerBinder;
         if (listener == null) {
             return;
@@ -71,6 +74,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
             listener.onUnpublish();
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Unpublish exception: " + e);
+            throw new ImsException("Remote is not available",
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -79,7 +84,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
      * request to the framework.
      */
     public void onRemoteCapabilityRequest(@NonNull Uri contactUri,
-            @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback) {
+            @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback)
+            throws ImsException {
         ICapabilityExchangeEventListener listener = mListenerBinder;
         if (listener == null) {
             return;
@@ -87,10 +93,11 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
 
         IOptionsRequestCallback internalCallback = new IOptionsRequestCallback.Stub() {
             @Override
-            public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities) {
+            public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities,
+                    boolean isBlocked) {
                 final long callingIdentity = Binder.clearCallingIdentity();
                 try {
-                    callback.onRespondToCapabilityRequest(ownCapabilities);
+                    callback.onRespondToCapabilityRequest(ownCapabilities, isBlocked);
                 } finally {
                     restoreCallingIdentity(callingIdentity);
                 }
@@ -110,6 +117,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
             listener.onRemoteCapabilityRequest(contactUri, remoteCapabilities, internalCallback);
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Remote capability request exception: " + e);
+            throw new ImsException("Remote is not available",
+                    ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 }
diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
index d4d5301f38fabe22bcab8388fef5598c6114aaa1..8eecbca7e6a767e0b493096d33cb5e22bbca8b6f 100644
--- a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
@@ -27,8 +27,9 @@ oneway interface IOptionsRequestCallback {
      * Respond to a remote capability request from the contact specified with the capabilities
      * of this device.
      * @param ownCapabilities The capabilities of this device.
+     * @param isBlocked True if the user has blocked the number sending this request.
      */
-    void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities);
+    void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities, boolean isBlocked);
 
     /**
      * Respond to a remote capability request from the contact specified with the
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index d9734a7475c067f4883208335c4df30079481fe6..4967e5da7c9a7ab2c8b82f05d872eb2da83b28ea 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -16,32 +16,58 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.net.Uri;
 import android.telephony.ims.ImsException;
 import android.telephony.ims.RcsContactUceCapability;
 import android.telephony.ims.RcsUceAdapter;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.RcsFeature;
+import android.util.Log;
+
+import java.util.List;
 
 /**
- * The interface of the capabilities event listener for ImsService to notify the framework of the
- * UCE request and status updated.
+ * The interface that is used by the framework to listen to events from the vendor RCS stack
+ * regarding capabilities exchange using presence server and OPTIONS.
  * @hide
  */
 @SystemApi
 public interface CapabilityExchangeEventListener {
     /**
      * Interface used by the framework to respond to OPTIONS requests.
-     * @hide
      */
     interface OptionsRequestCallback {
         /**
          * Respond to a remote capability request from the contact specified with the
          * capabilities of this device.
          * @param ownCapabilities The capabilities of this device.
+         * @hide
          */
-        void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities);
+        default void onRespondToCapabilityRequest(
+                @NonNull RcsContactUceCapability ownCapabilities) {}
+
+        /**
+         * Respond to a remote capability request from the contact specified with the
+         * capabilities of this device.
+         * @param ownCapabilities The capabilities of this device.
+         * @param isBlocked Whether or not the user has blocked the number requesting the
+         *         capabilities of this device. If true, the device should respond to the OPTIONS
+         *         request with a 200 OK response and no capabilities.
+         */
+        default void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities,
+                boolean isBlocked) {
+            Log.w("CapabilityExchangeEventListener", "implement "
+                    + "onRespondToCapabilityRequest(RcsContactUceCapability, boolean) instead!");
+            // Fall back to old implementation
+            if (isBlocked) {
+                onRespondToCapabilityRequestWithError(200, "OK");
+            } else {
+                onRespondToCapabilityRequest(ownCapabilities);
+            }
+        }
 
         /**
          * Respond to a remote capability request from the contact specified with the
@@ -49,7 +75,8 @@ public interface CapabilityExchangeEventListener {
          * @param code The SIP response code to respond with.
          * @param reason A non-null String containing the reason associated with the SIP code.
          */
-        void onRespondToCapabilityRequestWithError(int code, @NonNull String reason);
+        void onRespondToCapabilityRequestWithError(@IntRange(from = 100, to = 699) int code,
+                @NonNull String reason);
     }
 
     /**
@@ -59,8 +86,7 @@ public interface CapabilityExchangeEventListener {
      * This is typically used when trying to generate an initial PUBLISH for a new subscription to
      * the network. The device will cache all presence publications after boot until this method is
      * called the first time.
-     * @param publishTriggerType {@link RcsUceAdapter#StackPublishTriggerType} The reason for the
-     * capability update request.
+     * @param publishTriggerType The reason for the capability update request.
      * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not currently
      * connected to the framework. This can happen if the {@link RcsFeature} is not
      * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
@@ -81,4 +107,25 @@ public interface CapabilityExchangeEventListener {
      * Telephony stack has crashed.
      */
     void onUnpublish() throws ImsException;
+
+    /**
+     * Inform the framework of an OPTIONS query from a remote device for this device's UCE
+     * capabilities.
+     * <p>
+     * The framework will respond via the
+     * {@link OptionsRequestCallback#onRespondToCapabilityRequest} or
+     * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}.
+     * @param contactUri The URI associated with the remote contact that is
+     * requesting capabilities.
+     * @param remoteCapabilities The remote contact's capability information.
+     * @param callback The callback of this request which is sent from the remote user.
+     * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not
+     * currently connected to the framework. This can happen if the {@link RcsFeature} is not
+     * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+     * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
+     * cases when the Telephony stack has crashed.
+     */
+    void onRemoteCapabilityRequest(@NonNull Uri contactUri,
+            @NonNull List<String> remoteCapabilities,
+            @NonNull OptionsRequestCallback callback) throws ImsException;
 }
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index ec98be6e50626ace0d0e3f5802993a0bac01868b..908869beb6077553832eceabae3d740d298ae90c 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -19,7 +19,6 @@ package android.telephony.ims.stub;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
 import android.net.Uri;
@@ -141,7 +140,7 @@ public class RcsCapabilityExchangeImplBase {
          * {@link #publishCapabilities(String, PublishResponseCallback)}.
          *
          * If this network response also contains a “Reason” header, then the
-         * {@link onNetworkResponse(int, String, int, String)} method should be used instead.
+         * {@link #onNetworkResponse(int, String, int, String)} method should be used instead.
          *
          * @param sipCode The SIP response code sent from the network for the operation
          * token specified.
@@ -160,7 +159,7 @@ public class RcsCapabilityExchangeImplBase {
 
         /**
          * Provide the framework with a subsequent network response update to
-         * {@link #publishCapabilities(RcsContactUceCapability, int)} that also
+         * {@link #publishCapabilities(String, PublishResponseCallback)} that also
          * includes a reason provided in the “reason” header. See RFC3326 for more
          * information.
          *
@@ -186,7 +185,6 @@ public class RcsCapabilityExchangeImplBase {
 
     /**
      * Interface used by the framework to respond to OPTIONS requests.
-     * @hide
      */
     public interface OptionsResponseCallback {
         /**
@@ -217,7 +215,7 @@ public class RcsCapabilityExchangeImplBase {
          * cases when the Telephony stack has crashed.
          */
         void onNetworkResponse(int sipCode, @NonNull String reason,
-                @Nullable List<String> theirCaps) throws ImsException;
+                @NonNull List<String> theirCaps) throws ImsException;
     }
 
     /**
@@ -243,7 +241,7 @@ public class RcsCapabilityExchangeImplBase {
 
         /**
          * Notify the framework of the response to the SUBSCRIBE request from
-         * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}.
+         * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)}.
          * <p>
          * If the carrier network responds to the SUBSCRIBE request with a 2XX response, then the
          * framework will expect the IMS stack to call {@link #onNotifyCapabilitiesUpdate},
@@ -251,7 +249,7 @@ public class RcsCapabilityExchangeImplBase {
          * subsequent NOTIFY responses to the subscription.
          *
          * If this network response also contains a “Reason” header, then the
-         * {@link onNetworkResponse(int, String, int, String)} method should be used instead.
+         * {@link #onNetworkResponse(int, String, int, String)} method should be used instead.
          *
          * @param sipCode The SIP response code sent from the network for the operation
          * token specified.
@@ -268,7 +266,7 @@ public class RcsCapabilityExchangeImplBase {
 
         /**
          * Notify the framework  of the response to the SUBSCRIBE request from
-         * {@link #subscribeForCapabilities(RcsContactUceCapability, int)} that also
+         * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)} that also
          * includes a reason provided in the “reason” header. See RFC3326 for more
          * information.
          *
@@ -294,7 +292,8 @@ public class RcsCapabilityExchangeImplBase {
         /**
          * Notify the framework of the latest XML PIDF documents included in the network response
          * for the requested contacts' capabilities requested by the Framework using
-         * {@link RcsUceAdapter#requestCapabilities(Executor, List<Uri>, CapabilitiesCallback)}.
+         * {@link RcsUceAdapter#requestCapabilities(List, Executor,
+         * RcsUceAdapter.CapabilitiesCallback)}.
          * <p>
          * The expected format for the PIDF XML is defined in RFC3861. Each XML document must be a
          * "application/pidf+xml" object and start with a root <presence> element. For NOTIFY
@@ -336,7 +335,8 @@ public class RcsCapabilityExchangeImplBase {
 
         /**
          * The subscription associated with a previous
-         * {@link RcsUceAdapter#requestCapabilities(Executor, List<Uri>, CapabilitiesCallback)}
+         * {@link RcsUceAdapter#requestCapabilities(List, Executor,
+         * RcsUceAdapter.CapabilitiesCallback)}
          * operation has been terminated. This will mostly be due to the network sending a final
          * NOTIFY response due to the subscription expiring, but this may also happen due to a
          * network error.
@@ -427,12 +427,11 @@ public class RcsCapabilityExchangeImplBase {
      * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism
      * in order to receive the capabilities of the remote user in response.
      * <p>
-     * The implementer must call {@link #onNetworkResponse} to send the response of this
-     * query back to the framework.
+     * The implementer must use {@link OptionsResponseCallback} to send the response of
+     * this query from the network back to the framework.
      * @param contactUri The URI of the remote user that we wish to get the capabilities of.
      * @param myCapabilities The capabilities of this device to send to the remote user.
      * @param callback The callback of this request which is sent from the remote user.
-     * @hide
      */
     // executor used is defined in the constructor.
     @SuppressLint("ExecutorRegistration")