Supporting moving from a single sim to a DSDS and vice versa

Supporting moving from a single sim to a DSDS and vice versa

Bug: 213752236
Test: atest ImsProvisioningControllerTest
Change-Id: I26b386a6b69638aa8229b285300188a1249e33c7
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index b42f57f..2595e4b 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -39,6 +39,7 @@
 
 import android.annotation.Nullable;
 import android.content.Context;
+import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Looper;
@@ -64,6 +65,7 @@
 import com.android.ims.ImsManager;
 import com.android.ims.RcsFeatureManager;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.util.HandlerExecutor;
 import com.android.telephony.Rlog;
 
@@ -82,6 +84,8 @@
 
     private static final int EVENT_SUB_CHANGED = 1;
     private static final int EVENT_PROVISIONING_CAPABILITY_CHANGED = 2;
+    @VisibleForTesting
+    protected static final int EVENT_MULTI_SIM_CONFIGURATION_CHANGE = 3;
 
     // Provisioning Keys that are handled via AOSP cache and not sent to the ImsService
     private static final int[] LOCAL_IMS_CONFIG_KEYS = {
@@ -208,6 +212,10 @@
                                 "can not find callback manager message" + msg.what);
                     }
                     break;
+                case EVENT_MULTI_SIM_CONFIGURATION_CHANGE:
+                    int activeModemCount = (int) ((AsyncResult) msg.obj).result;
+                    onMultiSimConfigChanged(activeModemCount);
+                    break;
                 default:
                     log("unknown message " + msg);
                     break;
@@ -677,6 +685,9 @@
                 mSubChangedListener, mSubChangedListener.getHandlerExecutor());
         mImsProvisioningLoader = imsProvisioningLoader;
 
+        PhoneConfigurationManager.registerForMultiSimConfigChange(mHandler,
+                EVENT_MULTI_SIM_CONFIGURATION_CHANGE, null);
+
         initialize(numSlot);
     }
 
@@ -693,6 +704,39 @@
         }
     }
 
+    private void onMultiSimConfigChanged(int newNumSlot) {
+        log("onMultiSimConfigChanged: NumSlot " + mNumSlot + " newNumSlot " + newNumSlot);
+
+        if (mNumSlot < newNumSlot) {
+            for (int i = mNumSlot; i < newNumSlot; i++) {
+                MmTelFeatureListener m = new MmTelFeatureListener(i);
+                mMmTelFeatureListenersSlotMap.put(i, m);
+
+                RcsFeatureListener r = new RcsFeatureListener(i);
+                mRcsFeatureListenersSlotMap.put(i, r);
+
+                ProvisioningCallbackManager p = new ProvisioningCallbackManager(i);
+                mProvisioningCallbackManagersSlotMap.put(i, p);
+            }
+        } else if (mNumSlot > newNumSlot) {
+            for (int i = (mNumSlot - 1); i > (newNumSlot - 1); i--) {
+                MmTelFeatureListener m = mMmTelFeatureListenersSlotMap.get(i);
+                mMmTelFeatureListenersSlotMap.remove(i);
+                m.destroy();
+
+                RcsFeatureListener r = mRcsFeatureListenersSlotMap.get(i);
+                mRcsFeatureListenersSlotMap.remove(i);
+                r.destroy();
+
+                ProvisioningCallbackManager p = mProvisioningCallbackManagersSlotMap.get(i);
+                mProvisioningCallbackManagersSlotMap.remove(i);
+                p.clear();
+            }
+        }
+
+        mNumSlot = newNumSlot;
+    }
+
     /**
      * destroy the instance
      */
diff --git a/tests/src/com/android/phone/ImsProvisioningControllerTest.java b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
index 0ad9b60..01a6a2c 100644
--- a/tests/src/com/android/phone/ImsProvisioningControllerTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
@@ -35,7 +35,6 @@
 import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NR;
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
@@ -51,6 +50,7 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.IBinder;
@@ -299,7 +299,7 @@
         try {
             mTestImsProvisioningController.addFeatureProvisioningChangedCallback(mSubId0, null);
         } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            // expected result
         } catch (Exception e) {
             throw new AssertionError("not expected exception", e);
         }
@@ -314,7 +314,7 @@
         try {
             mTestImsProvisioningController.removeFeatureProvisioningChangedCallback(mSubId0, null);
         } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            // expected result
         } catch (Exception e) {
             throw new AssertionError("not expected exception", e);
         }
@@ -412,7 +412,7 @@
             mTestImsProvisioningController.isImsProvisioningRequiredForCapability(
                     mSubId0, MMTEL_CAPA_INVALID, RADIO_TECHS[0]);
         } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            // expected result
         } catch (Exception e) {
             throw new AssertionError("not expected exception", e);
         }
@@ -422,7 +422,7 @@
             mTestImsProvisioningController.isImsProvisioningRequiredForCapability(
                     mSubId0, MMTEL_CAPAS[0], RADIO_TECH_INVALID);
         } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            // expected result
         } catch (Exception e) {
             throw new AssertionError("not expected exception", e);
         }
@@ -473,7 +473,7 @@
             mTestImsProvisioningController.isRcsProvisioningRequiredForCapability(
                     mSubId0, RCS_CAPA_INVALID, RADIO_TECHS[0]);
         } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            // expected result
         } catch (Exception e) {
             throw new AssertionError("not expected exception", e);
         }
@@ -483,7 +483,7 @@
             mTestImsProvisioningController.isRcsProvisioningRequiredForCapability(
                     mSubId0, CAPABILITY_TYPE_PRESENCE_UCE, RADIO_TECH_INVALID);
         } catch (IllegalArgumentException e) {
-            assertTrue(true);
+            // expected result
         } catch (Exception e) {
             throw new AssertionError("not expected exception", e);
         }
@@ -920,7 +920,6 @@
         verifyNoMoreInteractions(mImsProvisioningLoader);
     }
 
-
     @Test
     @SmallTest
     public void setRcsProvisioningRequiredForCapability_withPresence() throws Exception {
@@ -1414,6 +1413,89 @@
         verifyNoMoreInteractions(mImsProvisioningLoader);
     }
 
+    @Test
+    @SmallTest
+    public void onMultiSimConfigChanged() throws Exception {
+        createImsProvisioningController();
+
+        // change number of slot 2 -> 1
+        mHandler.sendMessage(mHandler.obtainMessage(
+                mTestImsProvisioningController.EVENT_MULTI_SIM_CONFIGURATION_CHANGE,
+                0, 0, (Object) new AsyncResult(null, 1, null)));
+        processAllMessages();
+
+        // add callback with mSubId0, mPhoneId0 : Ok.
+        try {
+            mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+                    mSubId0, mIFeatureProvisioningCallback0);
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+
+        // add callbacks with new mSubId1, mPhoneId1 : IllegalArgumentException.
+        try {
+            mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+                    mSubId1, mIFeatureProvisioningCallback1);
+        } catch (IllegalArgumentException e) {
+            // expected result
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+        // check isImsProvisioningRequiredForCapability with mSubId1 : IllegalArgumentException
+        try {
+            mTestImsProvisioningController.isImsProvisioningRequiredForCapability(
+                    mSubId1, CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_LTE);
+        } catch (IllegalArgumentException e) {
+            // expected result
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+        clearInvocations(mIFeatureProvisioningCallback0);
+        clearInvocations(mIFeatureProvisioningCallback1);
+
+        // change number of slot 1 -> 2
+        mHandler.sendMessage(mHandler.obtainMessage(
+                mTestImsProvisioningController.EVENT_MULTI_SIM_CONFIGURATION_CHANGE,
+                0, 0, (Object) new AsyncResult(null, 2, null)));
+        processAllMessages();
+
+        // add callback with mSubId0, mPhoneId0 : Ok.
+        try {
+            mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+                    mSubId0, mIFeatureProvisioningCallback0);
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+
+        // add callbacks with new mSubId1, mPhoneId1 : Ok.
+        try {
+            mTestImsProvisioningController.addFeatureProvisioningChangedCallback(
+                    mSubId1, mIFeatureProvisioningCallback1);
+        } catch (Exception e) {
+            throw new AssertionError("not expected exception", e);
+        }
+        clearInvocations(mIFeatureProvisioningCallback0);
+        clearInvocations(mIFeatureProvisioningCallback1);
+
+        // check get,setImsProvisioningRequiredForCapability with mSubId1, mPhoneId1 : Ok
+        int capability = CAPABILITY_TYPE_VOICE;
+        int tech = REGISTRATION_TECH_LTE;
+        boolean provisioned;
+        provisioned = mTestImsProvisioningController.getImsProvisioningStatusForCapability(
+                mSubId1, capability, tech);
+        mTestImsProvisioningController.setImsProvisioningStatusForCapability(mSubId1,
+                capability, tech, !provisioned);
+        processAllMessages();
+
+        // verify weather Callback is called or not
+        verify(mIFeatureProvisioningCallback1, times(1))
+                .onFeatureProvisioningChanged(eq(capability), eq(tech), eq(!provisioned));
+
+        clearInvocations(mIFeatureProvisioningCallback0);
+        clearInvocations(mIFeatureProvisioningCallback1);
+        clearInvocations(mImsConfig);
+    }
+
     private void createImsProvisioningController() throws Exception {
         if (Looper.myLooper() == null) {
             Looper.prepare();