Better handle MSIM DDS changed event

On DSDS MSIM devices, when Default Data Subscription event
is received, the ImsService may choose to switch which
Slot ID is active.

This change better handles that switch and removes a
crash that was happening due to
ImsServiceProxy#getFeatureStatus getting called
circularly.

Bug: 37361882
Test: Run Telephony unit tests
Change-Id: I4aa1e7aa01a9c36bad5ef9c89f45a1a60671ca8b
diff --git a/src/java/com/android/ims/ImsManager.java b/src/java/com/android/ims/ImsManager.java
index 3f2d041..d10691d 100644
--- a/src/java/com/android/ims/ImsManager.java
+++ b/src/java/com/android/ims/ImsManager.java
@@ -1441,7 +1441,17 @@
         mImsConfigListener = listener;
     }
 
-    public void addNotifyStatusChangedCallback(ImsServiceProxy.INotifyStatusChanged c) {
+
+    /**
+     * Adds a callback for status changed events if the binder is already available. If it is not,
+     * this method will throw an ImsException.
+     */
+    public void addNotifyStatusChangedCallbackIfAvailable(ImsServiceProxy.INotifyStatusChanged c)
+            throws ImsException {
+        if (!mImsServiceProxy.isBinderAlive()) {
+            throw new ImsException("Binder is not active!",
+                    ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+        }
         if (c != null) {
             mStatusCallbacks.add(c);
         }
@@ -1852,8 +1862,6 @@
     }
 
     public int getImsServiceStatus() throws ImsException {
-        checkAndThrowExceptionIfServiceUnavailable();
-
         return mImsServiceProxy.getFeatureStatus();
     }
 
@@ -1985,7 +1993,8 @@
     }
 
     /**
-     * Binds the IMS service only if the service is not created.
+     * Checks to see if the ImsService Binder is connected. If it is not, we try to create the
+     * connection again.
      */
     private void checkAndThrowExceptionIfServiceUnavailable()
             throws ImsException {
@@ -2035,13 +2044,13 @@
         TelephonyManager tm = (TelephonyManager)
                 mContext.getSystemService(Context.TELEPHONY_SERVICE);
         ImsServiceProxy serviceProxy = new ImsServiceProxy(mPhoneId, ImsFeature.MMTEL);
+        serviceProxy.setStatusCallback(() ->  mStatusCallbacks.forEach(
+                ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged));
         // Returns null if the service is not available.
         IImsServiceController b = tm.getImsServiceControllerAndListen(mPhoneId,
                 ImsFeature.MMTEL, serviceProxy.getListener());
         if (b != null) {
             serviceProxy.setBinder(b.asBinder());
-            serviceProxy.setStatusCallback(() -> mStatusCallbacks.forEach(
-                            ImsServiceProxy.INotifyStatusChanged::notifyStatusChanged));
             // Trigger the cache to be updated for feature status.
             serviceProxy.getFeatureStatus();
         } else {
@@ -2061,9 +2070,13 @@
     private ImsCallSession createCallSession(int serviceId,
             ImsCallProfile profile) throws ImsException {
         try {
+            // Throws an exception if the ImsService Feature is not ready to accept commands.
             return new ImsCallSession(mImsServiceProxy.createCallSession(serviceId, profile, null));
         } catch (RemoteException e) {
-            return null;
+            Rlog.w(TAG, "CreateCallSession: Error, remote exception: " + e.getMessage());
+            throw new ImsException("createCallSession()", e,
+                    ImsReasonInfo.CODE_LOCAL_IMS_SERVICE_DOWN);
+
         }
     }