Merge "Correctly unregister listeners when MMTEL moves to not ready"
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index b4a1716..f428852 100755
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -90,7 +90,6 @@
 import com.android.ims.ImsEcbm;
 import com.android.ims.ImsException;
 import com.android.ims.ImsManager;
-import com.android.ims.ImsMultiEndpoint;
 import com.android.ims.ImsUtInterface;
 import com.android.ims.internal.ConferenceParticipant;
 import com.android.ims.internal.IImsCallSession;
@@ -993,7 +992,13 @@
     public void startListeningForCalls() throws ImsException {
         log("startListeningForCalls");
         mOperationLocalLog.log("startListeningForCalls - Connecting to ImsService");
-        mImsManager.open(mMmTelFeatureListener);
+        ImsExternalCallTracker externalCallTracker = mPhone.getExternalCallTracker();
+        ImsExternalCallTracker.ExternalCallStateListener externalCallStateListener =
+                externalCallTracker != null
+                        ? externalCallTracker.getExternalCallStateListener() : null;
+
+        mImsManager.open(mMmTelFeatureListener, mPhone.getImsEcbmStateListener(),
+                externalCallStateListener);
         mImsManager.addRegistrationCallback(mPhone.getImsMmTelRegistrationCallback(), this::post);
         mImsManager.addCapabilitiesCallback(mImsCapabilityCallback, this::post);
 
@@ -1001,8 +1006,6 @@
 
         mImsManager.getConfigInterface().addConfigCallback(mConfigCallback);
 
-        // Get the ECBM interface and set IMSPhone's listener object for notifications
-        getEcbmInterface().setEcbmStateListener(mPhone.getImsEcbmStateListener());
         if (mPhone.isInEcm()) {
             // Call exit ECBM which will invoke onECBMExited
             mPhone.exitEmergencyCallbackMode();
@@ -1013,17 +1016,12 @@
                 Phone.TTY_MODE_OFF);
         mImsManager.setUiTTYMode(mPhone.getContext(), mPreferredTtyMode, null);
 
-        ImsMultiEndpoint multiEndpoint = getMultiEndpointInterface();
-        if (multiEndpoint != null) {
-            multiEndpoint.setExternalCallStateListener(
-                    mPhone.getExternalCallTracker().getExternalCallStateListener());
-        }
-
-        //Set UT interface listener to receive UT indications.
+        // Set UT interface listener to receive UT indications & keep track of the interface so the
+        // handler reference can be cleared.
         mUtInterface = getUtInterface();
         if (mUtInterface != null) {
-            mUtInterface.registerForSuppServiceIndication(this,
-                    EVENT_SUPP_SERVICE_INDICATION, null);
+            mUtInterface.registerForSuppServiceIndication(this, EVENT_SUPP_SERVICE_INDICATION,
+                    null);
         }
 
         // Where device to device communication is available, ensure that the
@@ -1047,16 +1045,25 @@
     private void stopListeningForCalls() {
         log("stopListeningForCalls");
         mOperationLocalLog.log("stopListeningForCalls - Disconnecting from ImsService");
-        resetImsCapabilities();
         // Only close on valid session.
         if (mImsManager != null) {
+            mImsManager.removeRegistrationListener(mPhone.getImsMmTelRegistrationCallback());
+            mImsManager.removeCapabilitiesCallback(mImsCapabilityCallback);
             try {
+                mImsManager.setConfigListener(null);
                 mImsManager.getConfigInterface().removeConfigCallback(mConfigCallback.getBinder());
             } catch (ImsException e) {
                 Log.w(LOG_TAG, "stopListeningForCalls: unable to remove config callback.");
             }
+            // Will release other listeners for MMTEL/ECBM/UT/MultiEndpoint Indications set in #open
             mImsManager.close();
         }
+        if (mUtInterface != null) {
+            mUtInterface.unregisterForSuppServiceIndication(this);
+            mUtInterface = null;
+        }
+
+        resetImsCapabilities();
         hangupAllOrphanedConnections(DisconnectCause.LOST_SIGNAL);
         // For compatibility with apps that still use deprecated intent
         sendImsServiceStateIntent(ImsManager.ACTION_IMS_SERVICE_DOWN);
@@ -1113,9 +1120,6 @@
         mHandoverCall.dispose();
 
         clearDisconnected();
-        if (mUtInterface != null) {
-            mUtInterface.unregisterForSuppServiceIndication(this);
-        }
         mPhone.getContext().unregisterReceiver(mReceiver);
         mPhone.getDefaultPhone().getDataEnabledSettings().unregisterForDataEnabledChanged(this);
         mImsManagerConnector.disconnect();
@@ -3932,7 +3936,7 @@
             throw getImsManagerIsNullException();
         }
 
-        ImsUtInterface ut = mImsManager.getSupplementaryServiceConfiguration();
+        ImsUtInterface ut = mImsManager.createOrGetSupplementaryServiceConfiguration();
         return ut;
     }
 
@@ -4403,24 +4407,6 @@
         return ecbm;
     }
 
-    /* package */
-    ImsMultiEndpoint getMultiEndpointInterface() throws ImsException {
-        if (mImsManager == null) {
-            throw getImsManagerIsNullException();
-        }
-
-        try {
-            return mImsManager.getMultiEndpointInterface();
-        } catch (ImsException e) {
-            if (e.getCode() == ImsReasonInfo.CODE_MULTIENDPOINT_NOT_SUPPORTED) {
-                return null;
-            } else {
-                throw e;
-            }
-
-        }
-    }
-
     public boolean isInEmergencyCall() {
         return mIsInEmergencyCall;
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index 94c332c..51b8b33 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -210,7 +210,7 @@
         doAnswer(invocation -> {
             mMmTelListener = (MmTelFeature.Listener) invocation.getArguments()[0];
             return null;
-        }).when(mImsManager).open(any(MmTelFeature.Listener.class));
+        }).when(mImsManager).open(any(), any(), any());
 
         doAnswer(new Answer<ImsCall>() {
             @Override
@@ -770,8 +770,7 @@
                 eq(new String[]{"+17005554141"}), nullable(ImsCall.Listener.class));
         // Make sure that open is called in ImsPhoneCallTracker when it was first connected and
         // again after retry.
-        verify(mImsManager, times(2)).open(
-                nullable(MmTelFeature.Listener.class));
+        verify(mImsManager, times(2)).open(any(), any(), any());
     }
 
     @FlakyTest
@@ -788,8 +787,7 @@
         processAllMessages();
         // Make sure that open is called in ImsPhoneCallTracker to re-establish connection to
         // ImsService
-        verify(mImsManager, times(2)).open(
-                nullable(MmTelFeature.Listener.class));
+        verify(mImsManager, times(2)).open(any(), any(), any());
     }
 
     @Test