Merge "Ims: Add support to add participants to existing call"
diff --git a/src/java/com/android/ims/FeatureConnection.java b/src/java/com/android/ims/FeatureConnection.java
index 61fe732..158c55a 100644
--- a/src/java/com/android/ims/FeatureConnection.java
+++ b/src/java/com/android/ims/FeatureConnection.java
@@ -23,19 +23,15 @@
 import android.os.Looper;
 import android.os.RemoteException;
 import android.telephony.TelephonyManager;
-import android.telephony.ims.aidl.IImsMmTelFeature;
-import android.telephony.ims.aidl.IImsRcsFeature;
 import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.stub.ImsRegistrationImplBase;
-import com.android.telephony.Rlog;
 import android.util.Log;
 
 import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.util.HandlerExecutor;
 
-
 import java.util.concurrent.Executor;
 
 /**
diff --git a/src/java/com/android/ims/FeatureConnector.java b/src/java/com/android/ims/FeatureConnector.java
index 6b6dc60..273dd95 100644
--- a/src/java/com/android/ims/FeatureConnector.java
+++ b/src/java/com/android/ims/FeatureConnector.java
@@ -20,12 +20,12 @@
 import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Looper;
-import com.android.telephony.Rlog;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.feature.ImsFeature;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.util.HandlerExecutor;
+import com.android.telephony.Rlog;
 
 import java.util.concurrent.Executor;
 
@@ -46,11 +46,6 @@
 
     public interface Listener<T> {
         /**
-         * Check if ImsFeature supported
-         */
-        boolean isSupported();
-
-        /**
          * Get ImsFeature manager instance
          */
         T getFeatureManager();
@@ -96,14 +91,6 @@
         }
     };
 
-    public FeatureConnector(Context context, int phoneId, Listener<T> listener) {
-        mContext = context;
-        mPhoneId = phoneId;
-        mListener = listener;
-        mExecutor = new HandlerExecutor(this);
-        mLogPrefix = "?";
-    }
-
     public FeatureConnector(Context context, int phoneId, Listener<T> listener,
             String logPrefix) {
         mContext = context;
@@ -157,7 +144,7 @@
 
     // Check if this ImsFeature is supported or not.
     private boolean isSupported() {
-        return mListener.isSupported();
+        return ImsManager.isImsSupportedOnDevice(mContext);
     }
 
     /**
@@ -178,18 +165,18 @@
     private final Runnable mGetServiceRunnable = () -> {
         try {
             createImsService();
-        } catch (ImsException e) {
+        } catch (android.telephony.ims.ImsException e) {
             int errorCode = e.getCode();
             if (DBG) logw("Create IMS service error: " + errorCode);
-            if (ImsReasonInfo.CODE_LOCAL_IMS_NOT_SUPPORTED_ON_DEVICE != errorCode) {
-                // Retry when error is not IMS_NOT_SUPPORTED_ON_DEVICE
+            if (android.telephony.ims.ImsException.CODE_ERROR_UNSUPPORTED_OPERATION != errorCode) {
+                // Retry when error is not CODE_ERROR_UNSUPPORTED_OPERATION
                 retryGetImsService();
             }
         }
     };
 
     @VisibleForTesting
-    public void createImsService() throws ImsException {
+    public void createImsService() throws android.telephony.ims.ImsException {
         synchronized (mLock) {
             if (DBG) log("createImsService");
             mManager = mListener.getFeatureManager();
diff --git a/src/java/com/android/ims/IFeatureConnector.java b/src/java/com/android/ims/IFeatureConnector.java
index a169bb2..66428ce 100644
--- a/src/java/com/android/ims/IFeatureConnector.java
+++ b/src/java/com/android/ims/IFeatureConnector.java
@@ -16,9 +16,9 @@
 
 package com.android.ims;
 
-public interface IFeatureConnector {
+public interface IFeatureConnector<T> {
     int getImsServiceState() throws ImsException;
     void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate callback)
-            throws ImsException;
+            throws android.telephony.ims.ImsException;
     void removeNotifyStatusChangedCallback(FeatureConnection.IFeatureUpdate callback);
 }
\ No newline at end of file
diff --git a/src/java/com/android/ims/ImsCall.java b/src/java/com/android/ims/ImsCall.java
index 6291985..8d316dd 100644
--- a/src/java/com/android/ims/ImsCall.java
+++ b/src/java/com/android/ims/ImsCall.java
@@ -25,7 +25,6 @@
 import android.telecom.Call;
 import android.telecom.Connection;
 import android.telephony.CallQuality;
-import com.android.telephony.Rlog;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
@@ -41,6 +40,7 @@
 import com.android.ims.internal.ICall;
 import com.android.ims.internal.ImsStreamMediaSession;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
 import java.util.Iterator;
diff --git a/src/java/com/android/ims/ImsCallbackAdapterManager.java b/src/java/com/android/ims/ImsCallbackAdapterManager.java
index bf2bd39..d4926b2 100644
--- a/src/java/com/android/ims/ImsCallbackAdapterManager.java
+++ b/src/java/com/android/ims/ImsCallbackAdapterManager.java
@@ -35,7 +35,7 @@
 import java.util.stream.Collectors;
 
 public abstract class ImsCallbackAdapterManager<T extends IInterface> {
-    private static final String TAG = "ImsCallbackAdapterManager";
+    private static final String TAG = "ImsCallbackAM";
 
     private final Context mContext;
     private final Object mLock;
@@ -98,8 +98,8 @@
         };
     }
 
-    // Add a callback to the MmTelFeature associated with this manager (independent of the)
-    // current subscription.
+    // Add a callback to the ImsFeature associated with this manager (independent of the
+    // current subscription).
     public final void addCallback(T localCallback) {
         synchronized (mLock) {
             // Skip registering to callback subscription map here, because we are registering
@@ -124,7 +124,7 @@
         }
     }
 
-    // Removes a callback associated with the MmTelFeature.
+    // Removes a callback associated with the ImsFeature.
     public final void removeCallback(T localCallback) {
         Log.i(TAG + " [" + mSlotId + "]", "Local callback removed: " + localCallback);
         synchronized (mLock) {
@@ -255,9 +255,9 @@
         }
     }
 
-    // A callback has been registered. Register that callback with the MmTelFeature.
+    // A callback has been registered. Register that callback with the ImsFeature.
     public abstract void registerCallback(T localCallback);
 
-    // A callback has been removed, unregister that callback with the MmTelFeature.
+    // A callback has been removed, unregister that callback with the RcsFeature.
     public abstract void unregisterCallback(T localCallback);
 }
diff --git a/src/java/com/android/ims/ImsEcbm.java b/src/java/com/android/ims/ImsEcbm.java
index 32162eb..13a5925 100644
--- a/src/java/com/android/ims/ImsEcbm.java
+++ b/src/java/com/android/ims/ImsEcbm.java
@@ -31,11 +31,11 @@
 
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.RemoteException;
-import com.android.telephony.Rlog;
 import android.telephony.ims.ImsReasonInfo;
 
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsEcbmListener;
+import com.android.telephony.Rlog;
 
 /**
  * Provides APIs for the supplementary service settings using IMS (Ut interface).
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
index e219409..2e696ba 100644
--- a/src/java/com/android/ims/ImsManager.java
+++ b/src/java/com/android/ims/ImsManager.java
@@ -34,7 +34,6 @@
 import android.telecom.TelecomManager;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.CarrierConfigManager;
-import com.android.telephony.Rlog;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
@@ -63,6 +62,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.ITelephony;
 import com.android.internal.telephony.util.HandlerExecutor;
+import com.android.telephony.Rlog;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -193,6 +193,8 @@
      */
     public static final String EXTRA_IS_UNKNOWN_CALL = "android:isUnknown";
 
+    private static final int SUBINFO_PROPERTY_FALSE = 0;
+
     private static final int SYSTEM_PROPERTY_NOT_SET = -1;
 
     // -1 indicates a subscriptionProperty value that is never set.
@@ -1555,10 +1557,10 @@
     @Override
     @VisibleForTesting
     public void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate c)
-            throws ImsException {
+            throws android.telephony.ims.ImsException {
         if (!mMmTelFeatureConnection.isBinderAlive()) {
-            throw new ImsException("Binder is not active!",
-                    ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+            throw new android.telephony.ims.ImsException("Can not connect to ImsService",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
         if (c != null) {
             mStatusCallbacks.add(c);
@@ -2275,10 +2277,7 @@
     }
 
     /**
-     * Binds the IMS service to make/receive the call. Supports two methods of exposing an
-     * ImsService:
-     * 1) com.android.ims.ImsService implementation in ServiceManager (deprecated).
-     * 2) android.telephony.ims.ImsService implementation through ImsResolver.
+     * Creates a connection to the ImsService associated with this slot.
      */
     private void createImsService() {
         mMmTelFeatureConnection = MmTelFeatureConnection.create(mContext, mPhoneId);
@@ -2608,6 +2607,11 @@
             SubscriptionManager.setSubscriptionProperty(subId,
                     SubscriptionManager.VT_IMS_ENABLED,
                     Integer.toString(SUB_PROPERTY_NOT_INITIALIZED));
+
+            // Set RCS UCE to default
+            SubscriptionManager.setSubscriptionProperty(subId,
+                    SubscriptionManager.IMS_RCS_UCE_ENABLED, Integer.toString(
+                            SUBINFO_PROPERTY_FALSE));
         } else {
             loge("factoryReset: invalid sub id, can not reset siminfo db settings; subId=" + subId);
         }
@@ -2645,7 +2649,7 @@
     }
 
     private boolean isDataEnabled() {
-        return new TelephonyManager(mContext, getSubId()).isDataCapable();
+        return new TelephonyManager(mContext, getSubId()).isDataConnectionEnabled();
     }
 
     private boolean isVolteProvisioned() {
@@ -2696,7 +2700,8 @@
 
         pw.println("  isWfcEnabledByPlatform = " + isWfcEnabledByPlatform());
         pw.println("  isWfcEnabledByUser = " + isWfcEnabledByUser());
-        pw.println("  getWfcMode = " + getWfcMode());
+        pw.println("  getWfcMode(non-roaming) = " + getWfcMode(false));
+        pw.println("  getWfcMode(roaming) = " + getWfcMode(true));
         pw.println("  isWfcRoamingEnabledByUser = " + isWfcRoamingEnabledByUser());
 
         pw.println("  isVtProvisionedOnDevice = " + isVtProvisionedOnDevice());
diff --git a/src/java/com/android/ims/ImsMultiEndpoint.java b/src/java/com/android/ims/ImsMultiEndpoint.java
index 8a094d2..dc297b6 100644
--- a/src/java/com/android/ims/ImsMultiEndpoint.java
+++ b/src/java/com/android/ims/ImsMultiEndpoint.java
@@ -16,14 +16,14 @@
 
 package com.android.ims;
 
-import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsExternalCallStateListener;
-
 import android.os.RemoteException;
-import com.android.telephony.Rlog;
 import android.telephony.ims.ImsExternalCallState;
 import android.telephony.ims.ImsReasonInfo;
 
+import com.android.ims.internal.IImsExternalCallStateListener;
+import com.android.ims.internal.IImsMultiEndpoint;
+import com.android.telephony.Rlog;
+
 import java.util.List;
 
 /**
diff --git a/src/java/com/android/ims/ImsUt.java b/src/java/com/android/ims/ImsUt.java
index 513b7a0..61a1111 100644
--- a/src/java/com/android/ims/ImsUt.java
+++ b/src/java/com/android/ims/ImsUt.java
@@ -16,9 +16,6 @@
 
 package com.android.ims;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import android.content.res.Resources;
 import android.os.AsyncResult;
 import android.os.Bundle;
@@ -26,7 +23,6 @@
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RemoteException;
-import com.android.telephony.Rlog;
 import android.telephony.ims.ImsCallForwardInfo;
 import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.ImsSsData;
@@ -36,6 +32,10 @@
 import com.android.ims.internal.IImsUt;
 import com.android.ims.internal.IImsUtListener;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
+
+import java.util.HashMap;
+import java.util.Map;
 
 /**
  * Provides APIs for the supplementary service settings using IMS (Ut interface).
diff --git a/src/java/com/android/ims/MmTelFeatureConnection.java b/src/java/com/android/ims/MmTelFeatureConnection.java
index c3080a5..40075bc 100644
--- a/src/java/com/android/ims/MmTelFeatureConnection.java
+++ b/src/java/com/android/ims/MmTelFeatureConnection.java
@@ -17,17 +17,10 @@
 package com.android.ims;
 
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.content.Context;
 import android.os.IBinder;
-import android.os.IInterface;
-import android.os.Looper;
 import android.os.Message;
-import android.os.RemoteCallbackList;
 import android.os.RemoteException;
-import com.android.telephony.Rlog;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
 import android.telephony.ims.ImsCallProfile;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
@@ -40,24 +33,14 @@
 import android.telephony.ims.feature.CapabilityChangeRequest;
 import android.telephony.ims.feature.ImsFeature;
 import android.telephony.ims.feature.MmTelFeature;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.ims.stub.ImsSmsImplBase;
-import android.util.ArraySet;
 import android.util.Log;
-import android.util.SparseArray;
 
 import com.android.ims.internal.IImsCallSession;
 import com.android.ims.internal.IImsEcbm;
 import com.android.ims.internal.IImsMultiEndpoint;
-import com.android.ims.internal.IImsServiceFeatureCallback;
 import com.android.ims.internal.IImsUt;
-import com.android.internal.annotations.VisibleForTesting;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
+import com.android.telephony.Rlog;
 
 /**
  * A container of the IImsServiceController binder, which implements all of the ImsFeatures that
@@ -257,21 +240,11 @@
     @Override
     protected void onRemovedOrDied() {
         synchronized (mLock) {
+            super.onRemovedOrDied();
             mRegistrationCallbackManager.close();
             mCapabilityCallbackManager.close();
             mProvisioningCallbackManager.close();
-            if (mIsAvailable) {
-                mIsAvailable = false;
-                // invalidate caches.
-                mRegistrationBinder = null;
-                mConfigBinder = null;
-                if (mBinder != null) {
-                    mBinder.unlinkToDeath(mDeathRecipient, 0);
-                }
-                if (mStatusCallback != null) {
-                    mStatusCallback.notifyUnavailable();
-                }
-            }
+            mConfigBinder = null;
         }
     }
 
diff --git a/src/java/com/android/ims/RcsFeatureConnection.java b/src/java/com/android/ims/RcsFeatureConnection.java
index 714449d..daee6dd 100644
--- a/src/java/com/android/ims/RcsFeatureConnection.java
+++ b/src/java/com/android/ims/RcsFeatureConnection.java
@@ -20,33 +20,91 @@
 import android.content.Context;
 import android.os.IBinder;
 import android.os.RemoteException;
+import android.telephony.TelephonyManager;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
+import android.telephony.ims.aidl.IImsRcsFeature;
+import android.telephony.ims.aidl.IImsRegistration;
+import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsFeatureListener;
 import android.telephony.ims.feature.CapabilityChangeRequest;
 import android.telephony.ims.feature.ImsFeature;
-import android.telephony.ims.RcsContactUceCapability;
-import com.android.telephony.Rlog;
-import android.telephony.TelephonyManager;
-import android.telephony.ims.aidl.IImsRcsFeature;
-import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.service.ims.presence.PresencePublisher;
-import com.android.service.ims.presence.SubscribePublisher;
+import com.android.telephony.Rlog;
 
 /**
  * A container of the IImsServiceController binder, which implements all of the RcsFeatures that
  * the platform currently supports: RCS
  */
-public class RcsFeatureConnection extends FeatureConnection implements PresencePublisher,
-        SubscribePublisher {
+public class RcsFeatureConnection extends FeatureConnection {
     private static final String TAG = "RcsFeatureConnection";
 
-    public interface IRcsFeatureUpdate extends IFeatureUpdate {
-        /**
-         * Called when the ImsFeature has been created.
-         */
-        void notifyFeatureCreated();
+    public class AvailabilityCallbackManager extends
+            ImsCallbackAdapterManager<IImsCapabilityCallback> {
+
+        AvailabilityCallbackManager(Context context) {
+            super(context, new Object() /* Lock object */, mSlotId);
+        }
+
+        @Override
+        public void registerCallback(IImsCapabilityCallback localCallback) {
+            try {
+                addCapabilityCallback(localCallback);
+            } catch (RemoteException e) {
+                loge("Register capability callback error: " + e);
+                throw new IllegalStateException(
+                        " CapabilityCallbackManager: Register callback error");
+            }
+        }
+
+        @Override
+        public void unregisterCallback(IImsCapabilityCallback localCallback) {
+            try {
+                removeCapabilityCallback(localCallback);
+            } catch (RemoteException e) {
+                loge("Cannot remove capability callback: " + e);
+            }
+        }
+    }
+
+    private class RegistrationCallbackManager extends
+            ImsCallbackAdapterManager<IImsRegistrationCallback> {
+
+        public RegistrationCallbackManager(Context context) {
+            super(context, new Object() /* Lock object */, mSlotId);
+        }
+
+        @Override
+        public void registerCallback(IImsRegistrationCallback localCallback) {
+            IImsRegistration imsRegistration = getRegistration();
+            if (imsRegistration == null) {
+                loge("Register IMS registration callback: ImsRegistration is null");
+                throw new IllegalStateException("RegistrationCallbackAdapter: RcsFeature is"
+                        + " not available!");
+            }
+
+            try {
+                imsRegistration.addRegistrationCallback(localCallback);
+            } catch (RemoteException e) {
+                throw new IllegalStateException("RegistrationCallbackAdapter: RcsFeature"
+                        + " binder is dead.");
+            }
+        }
+
+        @Override
+        public void unregisterCallback(IImsRegistrationCallback localCallback) {
+            IImsRegistration imsRegistration = getRegistration();
+            if (imsRegistration == null) {
+                logi("Unregister IMS registration callback: ImsRegistration is null");
+                return;
+            }
+
+            try {
+                imsRegistration.removeRegistrationCallback(localCallback);
+            } catch (RemoteException e) {
+                loge("Cannot remove registration callback: " + e);
+            }
+        }
     }
 
     public static @NonNull RcsFeatureConnection create(Context context , int slotId,
@@ -83,51 +141,55 @@
     }
 
     @VisibleForTesting
-    public IRcsFeatureUpdate mRcsFeatureStatusCallback;
+    public AvailabilityCallbackManager mAvailabilityCallbackManager;
+    @VisibleForTesting
+    public RegistrationCallbackManager mRegistrationCallbackManager;
 
     private RcsFeatureConnection(Context context, int slotId, IFeatureUpdate callback) {
         super(context, slotId, ImsFeature.FEATURE_RCS);
         setStatusCallback(callback);
+        mAvailabilityCallbackManager = new AvailabilityCallbackManager(mContext);
+        mRegistrationCallbackManager = new RegistrationCallbackManager(mContext);
     }
 
     public void close() {
         removeRcsFeatureListener();
+        mAvailabilityCallbackManager.close();
+        mRegistrationCallbackManager.close();
     }
 
     @Override
-    public void setStatusCallback(IFeatureUpdate callback) {
-        super.setStatusCallback(callback);
-        mRcsFeatureStatusCallback = (IRcsFeatureUpdate) mStatusCallback;
+    protected void onRemovedOrDied() {
+        super.onRemovedOrDied();
+        synchronized (mLock) {
+            close();
+        }
     }
 
     @Override
     @VisibleForTesting
     public void handleImsFeatureCreatedCallback(int slotId, int feature) {
-        Log.i(TAG, "IMS feature created: slotId= " + slotId + ", feature=" + feature);
+        logi("IMS feature created: slotId= " + slotId + ", feature=" + feature);
         if (!isUpdateForThisFeatureAndSlot(slotId, feature)) {
             return;
         }
         synchronized(mLock) {
             if (!mIsAvailable) {
-                Log.i(TAG, "RCS enabled on slotId: " + slotId);
+                logi("RCS enabled on slotId: " + slotId);
                 mIsAvailable = true;
             }
-            // Notify RcsFeatureManager that RCS feature has already been created
-            if (mRcsFeatureStatusCallback != null) {
-              mRcsFeatureStatusCallback.notifyFeatureCreated();
-            }
         }
     }
 
     @Override
     @VisibleForTesting
     public void handleImsFeatureRemovedCallback(int slotId, int feature) {
-        Log.i(TAG, "IMS feature removed: slotId= " + slotId + ", feature=" + feature);
+        logi("IMS feature removed: slotId= " + slotId + ", feature=" + feature);
         if (!isUpdateForThisFeatureAndSlot(slotId, feature)) {
             return;
         }
         synchronized(mLock) {
-            Log.i(TAG, "Rcs UCE removed on slotId: " + slotId);
+            logi("Rcs UCE removed on slotId: " + slotId);
             onRemovedOrDied();
         }
     }
@@ -135,17 +197,13 @@
     @Override
     @VisibleForTesting
     public void handleImsStatusChangedCallback(int slotId, int feature, int status) {
-        Log.i(TAG, "IMS status changed: slotId=" + slotId
-                + ", feature=" + feature + ", status=" + status);
+        logi("IMS status changed: slotId=" + slotId + ", feature=" + feature + ", status="
+                + status);
         if (!isUpdateForThisFeatureAndSlot(slotId, feature)) {
             return;
         }
         synchronized(mLock) {
             mFeatureStateCached = status;
-            // notify RCS feature status changed
-            if (mRcsFeatureStatusCallback != null) {
-                mRcsFeatureStatusCallback.notifyStateChanged();
-            }
         }
     }
 
@@ -167,6 +225,7 @@
         try {
             setRcsFeatureListener(null);
         } catch (RemoteException e) {
+            // If we are not still connected, there is no need to fail removing.
         }
     }
 
@@ -177,14 +236,40 @@
         }
     }
 
-    public void addCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
+    public void addCallbackForSubscription(int subId, IImsCapabilityCallback cb) {
+        mAvailabilityCallbackManager.addCallbackForSubscription(cb, subId);
+    }
+
+    public void addCallbackForSubscription(int subId, IImsRegistrationCallback cb) {
+        mRegistrationCallbackManager.addCallbackForSubscription(cb, subId);
+    }
+
+    public void addCallback(IImsRegistrationCallback cb) {
+        mRegistrationCallbackManager.addCallback(cb);
+    }
+
+    public void removeCallbackForSubscription(int subId, IImsCapabilityCallback cb) {
+        mAvailabilityCallbackManager.removeCallbackForSubscription(cb, subId);
+    }
+
+    public void removeCallbackForSubscription(int subId, IImsRegistrationCallback cb) {
+        mRegistrationCallbackManager.removeCallbackForSubscription(cb, subId);
+    }
+
+    public void removeCallback(IImsRegistrationCallback cb) {
+        mRegistrationCallbackManager.removeCallback(cb);
+    }
+
+    // Add callback to remote service
+    private void addCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
         synchronized (mLock) {
             checkServiceIsReady();
             getServiceInterface(mBinder).addCapabilityCallback(callback);
         }
     }
 
-    public void removeCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
+    // Remove callback to remote service
+    private void removeCapabilityCallback(IImsCapabilityCallback callback) throws RemoteException {
         synchronized (mLock) {
             checkServiceIsReady();
             getServiceInterface(mBinder).removeCapabilityCallback(callback);
@@ -208,43 +293,6 @@
     }
 
     @Override
-    public int getPublisherState() {
-        // Need to implement this api
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int requestPublication(RcsContactUceCapability capabilities, String contactUri,
-            int taskId) {
-        // Need to implement this api
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public void updatePublisherState(int publishState) {
-        // Need to implement this api
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int requestCapability(String[] formattedContacts, int taskId) {
-        // Need to implement this api
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int requestAvailability(String formattedContact, int taskId) {
-        // Need to implement this api
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
-    public int getStackStatusForCapabilityRequest() {
-        // Need to implement this api
-        throw new UnsupportedOperationException();
-    }
-
-    @Override
     @VisibleForTesting
     public Integer retrieveFeatureState() {
         if (mBinder != null) {
@@ -261,4 +309,15 @@
     public IImsRcsFeature getServiceInterface(IBinder b) {
         return IImsRcsFeature.Stub.asInterface(b);
     }
+    private void log(String s) {
+        Rlog.d(TAG + " [" + mSlotId + "]", s);
+    }
+
+    private void logi(String s) {
+        Rlog.i(TAG + " [" + mSlotId + "]", s);
+    }
+
+    private void loge(String s) {
+        Rlog.e(TAG + " [" + mSlotId + "]", s);
+    }
 }
diff --git a/src/java/com/android/ims/RcsFeatureManager.java b/src/java/com/android/ims/RcsFeatureManager.java
index 41fc718..3fe9212 100644
--- a/src/java/com/android/ims/RcsFeatureManager.java
+++ b/src/java/com/android/ims/RcsFeatureManager.java
@@ -16,37 +16,43 @@
 
 package com.android.ims;
 
-import android.annotation.Nullable;
 import android.content.Context;
 import android.net.Uri;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
-import android.telephony.ims.ImsReasonInfo;
 import android.telephony.ims.RcsContactUceCapability;
+import android.telephony.ims.RegistrationManager;
 import android.telephony.ims.aidl.IImsCapabilityCallback;
-import android.telephony.ims.aidl.IImsRegistration;
 import android.telephony.ims.aidl.IImsRegistrationCallback;
 import android.telephony.ims.aidl.IRcsFeatureListener;
-import android.telephony.ims.stub.ImsRegistrationImplBase;
 import android.telephony.ims.feature.CapabilityChangeRequest;
+import android.telephony.ims.feature.RcsFeature;
 import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.telephony.ims.stub.RcsCapabilityExchange;
 import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
-import com.android.telephony.Rlog;
+import android.telephony.ims.stub.RcsSipOptionsImplBase;
 import android.util.Log;
 
 import com.android.ims.FeatureConnection.IFeatureUpdate;
-import com.android.ims.RcsFeatureConnection.IRcsFeatureUpdate;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.telephony.Rlog;
 
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Consumer;
 
+/**
+ * Encapsulates all logic related to the RcsFeature:
+ * - Updating RcsFeature capabilities.
+ * - Registering/Unregistering availability/registration callbacks.
+ * - Querying Registration and Capability information.
+ */
 public class RcsFeatureManager implements IFeatureConnector {
     private static final String TAG = "RcsFeatureManager";
     private static boolean DBG = true;
@@ -54,47 +60,109 @@
     private static final int CAPABILITY_OPTIONS = RcsImsCapabilities.CAPABILITY_TYPE_OPTIONS_UCE;
     private static final int CAPABILITY_PRESENCE = RcsImsCapabilities.CAPABILITY_TYPE_PRESENCE_UCE;
 
+    /**
+     * Callbacks from the RcsFeature, which have an empty default implementation and can be
+     * overridden for each Feature.
+     */
+    public static class RcsFeatureCallbacks {
+        /** See {@link RcsCapabilityExchange#onCommandUpdate(int, int)} */
+        void onCommandUpdate(int commandCode, int operationToken) {}
+
+        /** See {@link RcsPresenceExchangeImplBase#onNetworkResponse(int, String, int)} */
+        public void onNetworkResponse(int code, String reason, int operationToken) {}
+
+        /** See {@link RcsPresenceExchangeImplBase#onCapabilityRequestResponse(List, int)} */
+        public void onCapabilityRequestResponsePresence(List<RcsContactUceCapability> infos,
+                int operationToken) {}
+
+        /** See {@link RcsPresenceExchangeImplBase#onNotifyUpdateCapabilites(int)} */
+        public void onNotifyUpdateCapabilities(int publishTriggerType) {}
+
+        /** See {@link RcsPresenceExchangeImplBase#onUnpublish()} */
+        public void onUnpublish() {}
+
+        /**
+         * See {@link RcsSipOptionsImplBase#onCapabilityRequestResponse(int,String,
+         * RcsContactUceCapability, int)}
+         */
+        public void onCapabilityRequestResponseOptions(int code, String reason,
+                RcsContactUceCapability info, int operationToken) {}
+
+        /**
+         * See {@link RcsSipOptionsImplBase#onRemoteCapabilityRequest(Uri, RcsContactUceCapability,
+         * int)}
+         */
+        public void onRemoteCapabilityRequest(Uri contactUri, RcsContactUceCapability remoteInfo,
+                int operationToken) {}
+    }
+
+    private final IRcsFeatureListener mRcsFeatureCallbackAdapter = new IRcsFeatureListener.Stub() {
+        @Override
+        public void onCommandUpdate(int commandCode, int operationToken) {
+            mRcsFeatureCallbacks.forEach(listener-> listener.onCommandUpdate(commandCode,
+                    operationToken));
+        }
+
+        @Override
+        public void onNetworkResponse(int code, String reason, int operationToken) {
+            mRcsFeatureCallbacks.forEach(listener-> listener.onNetworkResponse(code, reason,
+                    operationToken));
+        }
+
+        @Override
+        public void onCapabilityRequestResponsePresence(List<RcsContactUceCapability> infos,
+                int operationToken) {
+            mRcsFeatureCallbacks.forEach(listener-> listener.onCapabilityRequestResponsePresence(
+                    infos, operationToken));
+        }
+
+        @Override
+        public void onNotifyUpdateCapabilities(int publishTriggerType) {
+            mRcsFeatureCallbacks.forEach(listener-> listener.onNotifyUpdateCapabilities(
+                    publishTriggerType));
+        }
+
+        @Override
+        public void onUnpublish() {
+            mRcsFeatureCallbacks.forEach(listener-> listener.onUnpublish());
+        }
+
+        @Override
+        public void onCapabilityRequestResponseOptions(int code, String reason,
+                RcsContactUceCapability info, int operationToken) {
+            mRcsFeatureCallbacks.forEach(listener -> listener.onCapabilityRequestResponseOptions(
+                    code, reason, info, operationToken));
+        }
+
+        @Override
+        public void onRemoteCapabilityRequest(Uri contactUri, RcsContactUceCapability remoteInfo,
+                int operationToken) {
+            mRcsFeatureCallbacks.forEach(listener -> listener.onRemoteCapabilityRequest(
+                    contactUri, remoteInfo, operationToken));
+        }
+    };
+
     private final int mSlotId;
     private final Context mContext;
+    @VisibleForTesting
+    public final Set<IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
+    private final Set<RcsFeatureCallbacks> mRcsFeatureCallbacks = new CopyOnWriteArraySet<>();
 
     @VisibleForTesting
     public RcsFeatureConnection mRcsFeatureConnection;
-    @VisibleForTesting
-    public RcsCapabilityCallbackManager mCapabilityCallbackManager;
-    @VisibleForTesting
-    public ImsRegistrationCallbackAdapter mRegistrationCallbackManager;
-    @VisibleForTesting
-    public Set<IFeatureUpdate> mStatusCallbacks = new CopyOnWriteArraySet<>();
 
     public RcsFeatureManager(Context context, int slotId) {
         mContext = context;
         mSlotId = slotId;
         logi("RcsFeatureManager");
 
-        mCapabilityCallbackManager = new RcsCapabilityCallbackManager(context);
-        mRegistrationCallbackManager = new ImsRegistrationCallbackAdapter(context);
-
         createImsService();
     }
 
-    public void release() {
-        logi("release");
-        mStatusCallbacks.clear();
-        mCapabilityCallbackManager.close();
-        mRegistrationCallbackManager.close();
-        mRcsFeatureConnection.close();
-    }
-
     // Binds the IMS service to the RcsFeature instance.
     private void createImsService() {
         mRcsFeatureConnection = RcsFeatureConnection.create(mContext, mSlotId,
-                new IRcsFeatureUpdate() {
-                    @Override
-                    public void notifyFeatureCreated() {
-                        logi("RcsFeature is created");
-                        setRcsFeatureListener();
-                        updateCapabilities();
-                    }
+                new IFeatureUpdate() {
                     @Override
                     public void notifyStateChanged() {
                         mStatusCallbacks.forEach(
@@ -110,148 +178,100 @@
     }
 
     /**
-     * Set RcsFeature listener and it will also trigger onFeatureReady in RcsFeature.
+     * Opens a persistent connection to the RcsFeature. This must be called before the RcsFeature
+     * can be used to communicate. Triggers a {@link RcsFeature#onFeatureReady()} call on the
+     * service side.
      */
-    private void setRcsFeatureListener() {
-        if (DBG) log("Set RcsFeature listener");
+    public void openConnection() throws android.telephony.ims.ImsException {
         try {
-            mRcsFeatureConnection.setRcsFeatureListener(mRcsFeatureListener);
-        } catch (RemoteException e) {
-            loge("setRcsFeatureListener: ", e);
+            mRcsFeatureConnection.setRcsFeatureListener(mRcsFeatureCallbackAdapter);
+        } catch (RemoteException e){
+            throw new android.telephony.ims.ImsException("Service is not available.",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
     /**
-     * Update current UCE capabilities.
+     * Closes the persistent connection to the RcsFeature. This must be called when this manager
+     * wishes to no longer be used to communicate with the RcsFeature.
      */
-    @VisibleForTesting
-    public void updateCapabilities() {
+    public void releaseConnection() {
+        try {
+            mRcsFeatureConnection.setRcsFeatureListener(null);
+        } catch (RemoteException e){
+            // Connection may not be available at this point.
+        }
+        mStatusCallbacks.clear();
+        mRcsFeatureConnection.close();
+        mRcsFeatureCallbacks.clear();
+    }
+
+    /**
+     * Adds a callback for {@link RcsFeatureCallbacks}.
+     * Note: These callbacks will be sent on the binder thread used to notify the callback.
+     */
+    public void addFeatureListenerCallback(RcsFeatureCallbacks listener) {
+        mRcsFeatureCallbacks.add(listener);
+    }
+
+    /**
+     * Removes an existing {@link RcsFeatureCallbacks}.
+     */
+    public void removeFeatureListenerCallback(RcsFeatureCallbacks listener) {
+        mRcsFeatureCallbacks.remove(listener);
+    }
+
+    /**
+     * Update the capabilities for this RcsFeature.
+     */
+    public void updateCapabilities() throws android.telephony.ims.ImsException {
         boolean optionsSupport = isOptionsSupported();
         boolean presenceSupported = isPresenceSupported();
 
-        if (DBG) log("Update capabilities: options=" + optionsSupport
+        logi("Update capabilities for slot " + mSlotId + ": options=" + optionsSupport
                 + ", presence=" + presenceSupported);
 
         if (optionsSupport || presenceSupported) {
+            CapabilityChangeRequest request = new CapabilityChangeRequest();
             if (optionsSupport) {
-                enableRcsUceCapability(CAPABILITY_OPTIONS);
+                addRcsUceCapability(request, CAPABILITY_OPTIONS);
             }
             if (presenceSupported) {
-                enableRcsUceCapability(CAPABILITY_PRESENCE);
+                addRcsUceCapability(request, CAPABILITY_PRESENCE);
             }
+            sendCapabilityChangeRequest(request);
         } else {
             disableAllRcsUceCapabilities();
         }
     }
 
-    public RcsFeatureConnection getRcsFeatureConnection() {
-        return mRcsFeatureConnection;
-    }
-
-    /**
-     * The callback to receive updated from RcsFeature
-     */
-    protected IRcsFeatureListener mRcsFeatureListener = new IRcsFeatureListener.Stub() {
-        @Override
-        public void onCommandUpdate(int commandCode, int operationToken) {
-        }
-
-        @Override
-        public void onNetworkResponse(int code, String reason, int operationToken) {
-        }
-
-        @Override
-        public void onCapabilityRequestResponsePresence(
-                List<RcsContactUceCapability> infos, int operationToken) {
-        }
-
-        @Override
-        public void onNotifyUpdateCapabilities(
-                @RcsPresenceExchangeImplBase.StackPublishTriggerType int triggerType) {
-        }
-
-        @Override
-        public void onUnpublish() {
-        }
-
-        @Override
-        public void onCapabilityRequestResponseOptions(
-                int code, String reason, RcsContactUceCapability info, int operationToken) {
-        }
-
-        @Override
-        public void onRemoteCapabilityRequest(
-                Uri contactUri, RcsContactUceCapability remoteInfo, int operationToken) {
-        }
-    };
-
-    /**
-     * A inner class to manager all the ImsRegistrationCallback associated with RcsFeature.
-     */
-    private class ImsRegistrationCallbackAdapter extends
-            ImsCallbackAdapterManager<IImsRegistrationCallback> {
-
-        public ImsRegistrationCallbackAdapter(Context context) {
-            super(context, new Object() /* Lock object */, mSlotId);
-        }
-
-        @Override
-        public void registerCallback(IImsRegistrationCallback localCallback) {
-            if (DBG) log("Register IMS registration callback");
-
-            IImsRegistration imsRegistration = getRegistration();
-            if (imsRegistration == null) {
-                loge("Register IMS registration callback: ImsRegistration is null");
-                throw new IllegalStateException("ImsRegistrationCallbackAdapter: RcsFeature is"
-                        + " not available!");
-            }
-
-            try {
-                imsRegistration.addRegistrationCallback(localCallback);
-            } catch (RemoteException e) {
-                throw new IllegalStateException("ImsRegistrationCallbackAdapter: RcsFeature"
-                        + " binder is dead.");
-            }
-        }
-
-        @Override
-        public void unregisterCallback(IImsRegistrationCallback localCallback) {
-            if (DBG) log("Unregister IMS registration callback");
-
-            IImsRegistration imsRegistration = getRegistration();
-            if (imsRegistration == null) {
-                log("Unregister IMS registration callback: ImsRegistration is null");
-                return;
-            }
-
-            try {
-                imsRegistration.removeRegistrationCallback(localCallback);
-            } catch (RemoteException e) {
-                loge("Cannot remove registration callback: " + e);
-            }
-        }
-
-        private @Nullable IImsRegistration getRegistration() {
-            if (mRcsFeatureConnection == null) {
-                return null;
-            }
-            return mRcsFeatureConnection.getRegistration();
-        }
-    }
-
     /**
      * Add a {@link RegistrationManager.RegistrationCallback} callback that gets called when IMS
      * registration has changed for a specific subscription.
      */
-    public void registerImsRegistrationCallback(IImsRegistrationCallback callback)
-            throws ImsException {
+    public void registerImsRegistrationCallback(int subId, IImsRegistrationCallback callback)
+            throws android.telephony.ims.ImsException {
         try {
-            int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
-            mRegistrationCallbackManager.addCallbackForSubscription(callback, subId);
+            mRcsFeatureConnection.addCallbackForSubscription(subId, callback);
         } catch (IllegalStateException e) {
             loge("registerImsRegistrationCallback error: ", e);
-            throw new ImsException(
-                    "register registration callback", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+            throw new android.telephony.ims.ImsException("Can not register callback",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+        }
+    }
+
+    /**
+     * Add a {@link RegistrationManager.RegistrationCallback} callback that gets called when IMS
+     * registration has changed, independent of the subscription it is currently on.
+     */
+    public void registerImsRegistrationCallback(IImsRegistrationCallback callback)
+            throws android.telephony.ims.ImsException {
+        try {
+            mRcsFeatureConnection.addCallback(callback);
+        } catch (IllegalStateException e) {
+            loge("registerImsRegistrationCallback error: ", e);
+            throw new android.telephony.ims.ImsException("Can not register callback",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -259,13 +279,16 @@
      * Removes a previously registered {@link RegistrationManager.RegistrationCallback} callback
      * that is associated with a specific subscription.
      */
+    public void unregisterImsRegistrationCallback(int subId, IImsRegistrationCallback callback) {
+        mRcsFeatureConnection.removeCallbackForSubscription(subId, callback);
+    }
+
+    /**
+     * Removes a previously registered {@link RegistrationManager.RegistrationCallback} callback
+     * that was not associated with a subscription.
+     */
     public void unregisterImsRegistrationCallback(IImsRegistrationCallback callback) {
-        try {
-            int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
-            mRegistrationCallbackManager.removeCallbackForSubscription(callback, subId);
-        } catch (IllegalStateException e) {
-            loge("unregisterImsRegistrationCallback error: ", e);
-        }
+        mRcsFeatureConnection.removeCallback(callback);
     }
 
     /**
@@ -283,68 +306,25 @@
     }
 
     /**
-     * A inner class to manager all the ImsCapabilityCallbacks associated with RcsFeature.
-     */
-    @VisibleForTesting
-    public class RcsCapabilityCallbackManager extends
-            ImsCallbackAdapterManager<IImsCapabilityCallback> {
-
-        RcsCapabilityCallbackManager(Context context) {
-            super(context, new Object() /* Lock object */, mSlotId);
-        }
-
-        @Override
-        public void registerCallback(IImsCapabilityCallback localCallback) {
-            if (DBG) log("Register capability callback");
-            try {
-                mRcsFeatureConnection.addCapabilityCallback(localCallback);
-            } catch (RemoteException e) {
-                loge("Register capability callback error: " + e);
-                throw new IllegalStateException(
-                        " CapabilityCallbackManager: Register callback error");
-            }
-        }
-
-        @Override
-        public void unregisterCallback(IImsCapabilityCallback localCallback) {
-            if (DBG) log("Unregister capability callback");
-            try {
-                mRcsFeatureConnection.removeCapabilityCallback(localCallback);
-            } catch (RemoteException e) {
-                loge("Cannot remove capability callback: " + e);
-            }
-        }
-    }
-
-    /**
      * Register an ImsCapabilityCallback with RCS service, which will provide RCS availability
      * updates.
      */
-    public void registerRcsAvailabilityCallback(IImsCapabilityCallback callback)
-            throws ImsException {
+    public void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback)
+            throws android.telephony.ims.ImsException {
         try {
-            int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
-            mCapabilityCallbackManager.addCallbackForSubscription(callback, subId);
+            mRcsFeatureConnection.addCallbackForSubscription(subId, callback);
         } catch (IllegalStateException e) {
             loge("registerRcsAvailabilityCallback: ", e);
-            throw new ImsException(
-                    "register capability callback", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+            throw new android.telephony.ims.ImsException("Can not register callback",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
     /**
      * Remove an registered ImsCapabilityCallback from RCS service.
      */
-    public void unregisterRcsAvailabilityCallback(IImsCapabilityCallback callback)
-            throws ImsException {
-        try {
-            int subId = sSubscriptionManagerProxy.getSubId(mSlotId);
-            mCapabilityCallbackManager.removeCallbackForSubscription(callback, subId);
-        } catch (IllegalStateException e) {
-            loge("unregisterRcsAvailabilityCallback: ", e);
-            throw new ImsException(
-                    "unregister capability callback", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
-        }
+    public void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback callback) {
+            mRcsFeatureConnection.removeCallbackForSubscription(subId, callback);
     }
 
     /**
@@ -352,7 +332,8 @@
      */
     public boolean isCapable(
             @RcsImsCapabilities.RcsImsCapabilityFlag int capability,
-            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException {
+            @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)
+            throws android.telephony.ims.ImsException {
         CountDownLatch latch = new CountDownLatch(1);
         AtomicReference<Boolean> capableRef = new AtomicReference<>();
 
@@ -386,7 +367,8 @@
             return awaitResult(latch, capableRef);
         } catch (RemoteException e) {
             loge("isCapable error: ", e);
-            throw new ImsException("is capable", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+            throw new android.telephony.ims.ImsException("Can not determine capabilities",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -403,13 +385,14 @@
      * Query the availability of an IMS RCS capability.
      */
     public boolean isAvailable(@RcsImsCapabilities.RcsImsCapabilityFlag int capability)
-            throws ImsException {
+            throws android.telephony.ims.ImsException {
         try {
             int currentStatus = mRcsFeatureConnection.queryCapabilityStatus();
             return new RcsImsCapabilities(currentStatus).isCapable(capability);
         } catch (RemoteException e) {
             loge("isAvailable error: ", e);
-            throw new ImsException("is RCS available", e, ImsReasonInfo.CODE_LOCAL_INTERNAL_ERROR);
+            throw new android.telephony.ims.ImsException("Can not determine availability",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -419,10 +402,10 @@
      */
     @Override
     public void addNotifyStatusChangedCallbackIfAvailable(FeatureConnection.IFeatureUpdate c)
-            throws ImsException {
+            throws android.telephony.ims.ImsException {
         if (!mRcsFeatureConnection.isBinderAlive()) {
-            throw new ImsException("Binder is not active!",
-                    ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+            throw new android.telephony.ims.ImsException("Can not connect to service.",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
         if (c != null) {
             mStatusCallbacks.add(c);
@@ -437,29 +420,21 @@
     }
 
     /**
-     * Enable UCE capabilities with given type.
+     * Add UCE capabilities with given type.
      * @param capability the specific RCS UCE capability wants to enable
      */
-    public void enableRcsUceCapability(
+    public void addRcsUceCapability(CapabilityChangeRequest request,
             @RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
-
-        CapabilityChangeRequest request = new CapabilityChangeRequest();
         request.addCapabilitiesToEnableForTech(capability,
                 ImsRegistrationImplBase.REGISTRATION_TECH_LTE);
         request.addCapabilitiesToEnableForTech(capability,
                 ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN);
-        try {
-            if (DBG) log("enableRcsUceCapability: " + capability);
-            mRcsFeatureConnection.changeEnabledCapabilities(request, null);
-        } catch (RemoteException e) {
-            loge("enableRcsUceCapability: ", e);
-        }
     }
 
     /**
      * Disable all of the UCE capabilities.
      */
-    private void disableAllRcsUceCapabilities() {
+    private void disableAllRcsUceCapabilities() throws android.telephony.ims.ImsException {
         final int techLte = ImsRegistrationImplBase.REGISTRATION_TECH_LTE;
         final int techIWlan = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN;
         CapabilityChangeRequest request = new CapabilityChangeRequest();
@@ -467,11 +442,17 @@
         request.addCapabilitiesToDisableForTech(CAPABILITY_OPTIONS, techIWlan);
         request.addCapabilitiesToDisableForTech(CAPABILITY_PRESENCE, techLte);
         request.addCapabilitiesToDisableForTech(CAPABILITY_PRESENCE, techIWlan);
+        sendCapabilityChangeRequest(request);
+    }
+
+    private void sendCapabilityChangeRequest(CapabilityChangeRequest request)
+            throws android.telephony.ims.ImsException {
         try {
-            if (DBG) log("disableAllRcsUceCapabilities");
+            if (DBG) log("sendCapabilityChangeRequest: " + request);
             mRcsFeatureConnection.changeEnabledCapabilities(request, null);
         } catch (RemoteException e) {
-            Log.e(TAG, "disableAllRcsUceCapabilities " + e);
+            throw new android.telephony.ims.ImsException("Can not connect to service",
+                    android.telephony.ims.ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
         }
     }
 
@@ -483,21 +464,6 @@
         return isCapabilityTypeSupported(mContext, mSlotId, CAPABILITY_PRESENCE);
     }
 
-    /**
-     * Check if RCS UCE feature is supported by carrier.
-     */
-    public static boolean isRcsUceSupportedByCarrier(Context context, int slotId) {
-        boolean isOptionsSupported = isCapabilityTypeSupported(
-            context, slotId, CAPABILITY_OPTIONS);
-        boolean isPresenceSupported = isCapabilityTypeSupported(
-            context, slotId, CAPABILITY_PRESENCE);
-
-        if (DBG) Log.d(TAG, "isRcsUceSupportedByCarrier: options=" + isOptionsSupported
-                + ", presence=" + isPresenceSupported);
-
-        return isOptionsSupported | isPresenceSupported;
-    }
-
     /*
      * Check if the given type of capability is supported.
      */
diff --git a/src/java/com/android/ims/internal/ConferenceParticipant.java b/src/java/com/android/ims/internal/ConferenceParticipant.java
index d09453f..12edd16 100644
--- a/src/java/com/android/ims/internal/ConferenceParticipant.java
+++ b/src/java/com/android/ims/internal/ConferenceParticipant.java
@@ -19,16 +19,14 @@
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telecom.Call;
 import android.telecom.Connection;
-import android.telecom.ParcelableCall;
 import android.telecom.PhoneAccount;
 import android.telephony.PhoneNumberUtils;
-import com.android.telephony.Rlog;
 import android.text.TextUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.PhoneConstants;
+import com.android.telephony.Rlog;
 
 /**
  * Parcelable representation of a participant's state in a conference call.
@@ -108,7 +106,7 @@
 
                 @Override
                 public ConferenceParticipant createFromParcel(Parcel source) {
-                    ClassLoader classLoader = ParcelableCall.class.getClassLoader();
+                    ClassLoader classLoader = ConferenceParticipant.class.getClassLoader();
                     Uri handle = source.readParcelable(classLoader);
                     String displayName = source.readString();
                     Uri endpoint = source.readParcelable(classLoader);
@@ -281,17 +279,23 @@
     }
 
     /**
-     * @return The direction of the call (incoming/outgoing).
+     * @return The direction of the call (incoming/outgoing):
+     *         {@link android.telecom.Call.Details#DIRECTION_INCOMING} for incoming calls, or
+     *         {@link android.telecom.Call.Details#DIRECTION_OUTGOING} for outgoing calls.
      */
-    public @android.telecom.Call.Details.CallDirection int getCallDirection() {
+    public int getCallDirection() {
         return mCallDirection;
     }
 
     /**
      * Sets the direction of the call.
-     * @param callDirection Whether the call is incoming or outgoing.
+     * @param callDirection Whether the call is incoming or outgoing:
+     *                      {@link android.telecom.Call.Details#DIRECTION_INCOMING} for
+     *                      incoming calls, or
+     *                      {@link android.telecom.Call.Details#DIRECTION_OUTGOING} for
+     *                      outgoing calls.
      */
-    public void setCallDirection(@Call.Details.CallDirection int callDirection) {
+    public void setCallDirection(int callDirection) {
         mCallDirection = callDirection;
     }