Ignore null binding on service died

When a service dies, sometimes it will send onNullBinding
after onServiceDied. This should be ingored or else we will
permanently unbind until the user reboots.

Bug: 161139847
Test: atest FrameworksTelephonyTests:ImsServiceControllerTest
Change-Id: I1b3ae578ad318d176e8fad86c4b768aebe9c893f
diff --git a/src/java/com/android/internal/telephony/ims/ImsServiceController.java b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
index bc5ddbe..e1bef176 100644
--- a/src/java/com/android/internal/telephony/ims/ImsServiceController.java
+++ b/src/java/com/android/internal/telephony/ims/ImsServiceController.java
@@ -69,6 +69,9 @@
 public class ImsServiceController {
 
     class ImsServiceConnection implements ServiceConnection {
+        // Track the status of whether or not the Service has died in case we need to permanently
+        // unbind (see onNullBinding below).
+        private boolean mIsServiceConnectionDead = false;
 
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
@@ -113,6 +116,7 @@
 
         @Override
         public void onBindingDied(ComponentName name) {
+            mIsServiceConnectionDead = true;
             synchronized (mLock) {
                 mIsBinding = false;
                 mIsBound = false;
@@ -129,8 +133,12 @@
 
         @Override
         public void onNullBinding(ComponentName name) {
-            Log.w(LOG_TAG, "ImsService(" + name + "): onNullBinding. Removing.");
-            mLocalLog.log("onNullBinding");
+            Log.w(LOG_TAG, "ImsService(" + name + "): onNullBinding. Is service dead = "
+                    + mIsServiceConnectionDead);
+            mLocalLog.log("onNullBinding, is service dead = " + mIsServiceConnectionDead);
+            // onNullBinding will happen after onBindingDied. In this case, we should not
+            // permanently unbind and instead let the automatic rebind occur.
+            if (mIsServiceConnectionDead) return;
             synchronized (mLock) {
                 mIsBinding = false;
                 mIsBound = false;
diff --git a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
index ff17216..0942822 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/ims/ImsServiceControllerTest.java
@@ -562,6 +562,30 @@
     }
 
     /**
+     * Due to a bug in ServiceConnection, we will sometimes receive a null binding after the binding
+     * dies. Ignore null binding in this case.
+     */
+    @SmallTest
+    @Test
+    public void testAutoBindAfterBinderDiedIgnoreNullBinding() throws RemoteException {
+        HashSet<ImsFeatureConfiguration.FeatureSlotPair> testFeatures = new HashSet<>();
+        testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+                ImsFeature.FEATURE_MMTEL));
+        testFeatures.add(new ImsFeatureConfiguration.FeatureSlotPair(SLOT_0,
+                ImsFeature.FEATURE_RCS));
+        ServiceConnection conn = bindAndConnectService(testFeatures);
+
+        conn.onBindingDied(null);
+        // null binding should be ignored in this case.
+        conn.onNullBinding(null);
+
+        long delay = mTestImsServiceController.getRebindDelay();
+        waitForHandlerActionDelayed(mHandler, delay, 2 * delay);
+        // The service should autobind after rebind event occurs
+        verify(mMockContext, times(2)).bindService(any(), any(), anyInt());
+    }
+
+    /**
      * Ensure that bindService has only been called once before automatic rebind occurs.
      */
     @SmallTest