Have UiccController compitible with dynamicy ss <-> ds switch

Test: manual and unittest
Bug: 142514392
Merged-In: Ic011551f184ebc5e98ba09089e54038086b041cb
Change-Id: Ic011551f184ebc5e98ba09089e54038086b041cb
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 1e712b0..a3177c6 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -16,6 +16,9 @@
 
 package com.android.internal.telephony;
 
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA;
+import static com.android.internal.telephony.PhoneConstants.PHONE_TYPE_CDMA_LTE;
+
 import android.annotation.Nullable;
 import android.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -164,7 +167,7 @@
 
                 // Instantiate UiccController so that all other classes can just
                 // call getInstance()
-                sUiccController = UiccController.make(context, sCommandsInterfaces);
+                sUiccController = UiccController.make(context);
 
                 Rlog.i(LOG_TAG, "Creating SubscriptionController");
                 SubscriptionController sc = SubscriptionController.init(context);
@@ -177,22 +180,7 @@
                 }
 
                 for (int i = 0; i < numPhones; i++) {
-                    Phone phone = null;
-                    int phoneType = TelephonyManager.getPhoneType(networkModes[i]);
-                    if (phoneType == PhoneConstants.PHONE_TYPE_GSM) {
-                        phone = new GsmCdmaPhone(context,
-                                sCommandsInterfaces[i], sPhoneNotifier, i,
-                                PhoneConstants.PHONE_TYPE_GSM,
-                                TelephonyComponentFactory.getInstance());
-                    } else if (phoneType == PhoneConstants.PHONE_TYPE_CDMA) {
-                        phone = new GsmCdmaPhone(context,
-                                sCommandsInterfaces[i], sPhoneNotifier, i,
-                                PhoneConstants.PHONE_TYPE_CDMA_LTE,
-                                TelephonyComponentFactory.getInstance());
-                    }
-                    Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " sub = " + i);
-
-                    sPhones[i] = phone;
+                    sPhones[i] = createPhone(context, i);
                 }
 
                 // Set the default phone in base class.
@@ -274,6 +262,18 @@
         }
     }
 
+    private static Phone createPhone(Context context, int phoneId) {
+        int phoneType = TelephonyManager.getPhoneType(RILConstants.PREFERRED_NETWORK_MODE);
+        Rlog.i(LOG_TAG, "Creating Phone with type = " + phoneType + " phoneId = " + phoneId);
+
+        // We always use PHONE_TYPE_CDMA_LTE now.
+        if (phoneType == PHONE_TYPE_CDMA) phoneType = PHONE_TYPE_CDMA_LTE;
+
+        return new GsmCdmaPhone(context,
+                sCommandsInterfaces[phoneId], sPhoneNotifier, phoneId, phoneType,
+                TelephonyComponentFactory.getInstance());
+    }
+
     @UnsupportedAppUsage
     public static Phone getDefaultPhone() {
         synchronized (sLockProxyPhones) {
@@ -459,6 +459,15 @@
     }
 
     /**
+     * Get Command Interfaces.
+     */
+    public static CommandsInterface[] getCommandsInterfaces() {
+        synchronized (sLockProxyPhones) {
+            return sCommandsInterfaces;
+        }
+    }
+
+    /**
      * Adds a local log category.
      *
      * Only used within the telephony process.  Use localLog to add log entries.
diff --git a/src/java/com/android/internal/telephony/uicc/UiccController.java b/src/java/com/android/internal/telephony/uicc/UiccController.java
index 6112dda..a7bce9c 100644
--- a/src/java/com/android/internal/telephony/uicc/UiccController.java
+++ b/src/java/com/android/internal/telephony/uicc/UiccController.java
@@ -19,6 +19,8 @@
 import static android.telephony.TelephonyManager.UNINITIALIZED_CARD_ID;
 import static android.telephony.TelephonyManager.UNSUPPORTED_CARD_ID;
 
+import static java.util.Arrays.copyOf;
+
 import android.annotation.UnsupportedAppUsage;
 import android.app.BroadcastOptions;
 import android.content.Context;
@@ -43,6 +45,7 @@
 import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.IccCardConstants;
+import com.android.internal.telephony.PhoneConfigurationManager;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.RadioConfig;
@@ -121,6 +124,7 @@
     private static final int EVENT_RADIO_UNAVAILABLE = 7;
     private static final int EVENT_SIM_REFRESH = 8;
     private static final int EVENT_EID_READY = 9;
+    private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 10;
 
     // this needs to be here, because on bootup we dont know which index maps to which UiccSlot
     @UnsupportedAppUsage
@@ -187,20 +191,23 @@
     // LocalLog buffer to hold important SIM related events for debugging
     static LocalLog sLocalLog = new LocalLog(100);
 
-    public static UiccController make(Context c, CommandsInterface[] ci) {
+    /**
+     * API to make UiccController singleton if not already created.
+     */
+    public static UiccController make(Context c) {
         synchronized (mLock) {
             if (mInstance != null) {
                 throw new RuntimeException("UiccController.make() should only be called once");
             }
-            mInstance = new UiccController(c, ci);
+            mInstance = new UiccController(c);
             return mInstance;
         }
     }
 
-    private UiccController(Context c, CommandsInterface []ci) {
+    private UiccController(Context c) {
         if (DBG) log("Creating UiccController");
         mContext = c;
-        mCis = ci;
+        mCis = PhoneFactory.getCommandsInterfaces();
         if (DBG) {
             String logStr = "config_num_physical_slots = " + c.getResources().getInteger(
                     com.android.internal.R.integer.config_num_physical_slots);
@@ -216,7 +223,7 @@
         }
 
         mUiccSlots = new UiccSlot[numPhysicalSlots];
-        mPhoneIdToSlotId = new int[ci.length];
+        mPhoneIdToSlotId = new int[mCis.length];
         Arrays.fill(mPhoneIdToSlotId, INVALID_SLOT_ID);
         if (VDBG) logPhoneIdToSlotIdMapping();
         mRadioConfig = RadioConfig.getInstance(mContext);
@@ -245,6 +252,9 @@
         mEuiccSlots = mContext.getResources()
                 .getIntArray(com.android.internal.R.array.non_removable_euicc_slots);
         mHasBuiltInEuicc = hasBuiltInEuicc();
+
+        PhoneConfigurationManager.registerForMultiSimConfigChange(
+                this, EVENT_MULTI_SIM_CONFIG_CHANGED, null);
     }
 
     /**
@@ -519,6 +529,9 @@
                     if (DBG) log("Received EVENT_EID_READY");
                     onEidReady(ar, phoneId);
                     break;
+                case EVENT_MULTI_SIM_CONFIG_CHANGED:
+                    if (DBG) log("Received EVENT_MULTI_SIM_CONFIG_CHANGED");
+                    onMultiSimConfigChanged();
                 default:
                     Rlog.e(LOG_TAG, " Unknown Event " + msg.what);
                     break;
@@ -526,6 +539,32 @@
         }
     }
 
+    private void onMultiSimConfigChanged() {
+        int prevActiveModemCount = mCis.length;
+        mCis = PhoneFactory.getCommandsInterfaces();
+
+        // Resize array.
+        mPhoneIdToSlotId = copyOf(mPhoneIdToSlotId, mCis.length);
+
+        for (int i = prevActiveModemCount; i < mCis.length; i++) {
+            mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i);
+
+            /*
+             * To support FDE (deprecated), additional check is needed:
+             *
+             * if (!StorageManager.inCryptKeeperBounce()) {
+             *     mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i);
+             * } else {
+             *     mCis[i].registerForOn(this, EVENT_RADIO_ON, i);
+             * }
+             */
+            mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i);
+
+            mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i);
+            mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i);
+        }
+    }
+
     private Integer getCiIndex(Message msg) {
         AsyncResult ar;
         Integer index = new Integer(PhoneConstants.DEFAULT_SLOT_INDEX);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
index 804bdf1..336267c 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/uicc/UiccControllerTest.java
@@ -39,7 +39,6 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.uicc.euicc.EuiccCard;
 
@@ -52,6 +51,7 @@
 
 import java.util.ArrayList;
 
+
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
 public class UiccControllerTest extends TelephonyTest {
@@ -109,8 +109,7 @@
         // for testing we pretend slotIndex is set. In reality it would be invalid on older versions
         // (before 1.2) of hal
         mIccCardStatus.physicalSlotIndex = 0;
-        mUiccControllerUT = UiccController.make(mContext,
-            new CommandsInterface[]{mSimulatedCommands});
+        mUiccControllerUT = UiccController.make(mContext);
         // reset sLastSlotStatus so that onGetSlotStatusDone always sees a change in the slot status
         mUiccControllerUT.sLastSlotStatus = null;
         processAllMessages();
@@ -131,8 +130,7 @@
                 com.android.internal.R.array.non_removable_euicc_slots,
                 nonRemovableEuiccSlots);
         replaceInstance(UiccController.class, "mInstance", null, null);
-        mUiccControllerUT = UiccController.make(mContext,
-            new CommandsInterface[]{mSimulatedCommands});
+        mUiccControllerUT = UiccController.make(mContext);
         processAllMessages();
     }