[Settings] Support of Primary IMEI feature

Present primary IMEI information when there're multiple.

Bug: 260188417
Test: local

Change-Id: I7817fed506f8fc4fabd94f004c9a74b2fab25e10
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 31e5de4..05983d8 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2470,7 +2470,9 @@
     <!-- About phone, title of EID for multi-sim devices -->
     <string name="eid_multi_sim">EID (sim slot <xliff:g id="eid_slot_id">%1$d</xliff:g>)</string>
     <!-- About phone screen, title for IMEI for multi-sim devices -->
-    <string name="imei_multi_sim">IMEI (sim slot %1$d)</string>
+    <string name="imei_multi_sim">IMEI (sim slot <xliff:g id="imei_slot_id">%1$d</xliff:g>)</string>
+    <!-- About phone screen, title for primary IMEI for multi-sim devices -->
+    <string name="imei_multi_sim_primary">IMEI (sim slot <xliff:g id="imei_slot_id_primary">%1$d</xliff:g>) (primary)</string>
     <!-- About phone screen, summary of the MAC address [CHAR LIMIT=80] -->
     <string name="view_saved_network">To view, choose saved network</string>
     <!-- Do not translate. About phone, status item title -->
@@ -2486,7 +2488,9 @@
     <!-- About phone, status item title.  The phone PRL Version of the current device.-->
     <string name="status_prl_version">PRL version</string>
     <!-- About phone screen, title for MEID for multi-sim devices -->
-    <string name="meid_multi_sim">MEID (sim slot %1$d)</string>
+    <string name="meid_multi_sim">MEID (sim slot <xliff:g id="meid_slot_id">%1$d</xliff:g>)</string>
+    <!-- About phone screen, title for primary MEID for multi-sim devices -->
+    <string name="meid_multi_sim_primary">MEID (sim slot <xliff:g id="meid_slot_id_primary">%1$d</xliff:g>) (primary)</string>
     <!-- About phone, status item title.  The phone MEID number of the current LTE/CDMA device. [CHAR LIMIT=30] -->
     <string name="status_meid_number">MEID</string>
     <!-- About phone, status item title.  The ICCID of the current LTE device. [CHAR LIMIT=30] -->
diff --git a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
index 991ad25..5e5e2ab 100644
--- a/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
+++ b/src/com/android/settings/deviceinfo/aboutphone/MyDeviceInfoFragment.java
@@ -55,6 +55,7 @@
 import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.function.Consumer;
 
 @SearchIndexable
 public class MyDeviceInfoFragment extends DashboardFragment
@@ -79,7 +80,6 @@
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
-        use(ImeiInfoPreferenceController.class).setHost(this /* parent */);
         use(DeviceNamePreferenceController.class).setHost(this /* parent */);
         mBuildNumberPreferenceController = use(BuildNumberPreferenceController.class);
         mBuildNumberPreferenceController.setHost(this /* parent */);
@@ -126,12 +126,27 @@
         controllers.add(new FccEquipmentIdPreferenceController(context));
         controllers.add(new UptimePreferenceController(context, lifecycle));
 
+        Consumer<String> imeiInfoList = imeiKey -> {
+            ImeiInfoPreferenceController imeiRecord =
+                    new ImeiInfoPreferenceController(context, imeiKey);
+            imeiRecord.init(fragment, slotSimStatus);
+            controllers.add(imeiRecord);
+        };
+
+        if (fragment != null) {
+            imeiInfoList.accept(ImeiInfoPreferenceController.DEFAULT_KEY);
+        }
+
         for (int slotIndex = 0; slotIndex < slotSimStatus.size(); slotIndex ++) {
             SimStatusPreferenceController slotRecord =
                     new SimStatusPreferenceController(context,
                     slotSimStatus.getPreferenceKey(slotIndex));
             slotRecord.init(fragment, slotSimStatus);
             controllers.add(slotRecord);
+
+            if (fragment != null) {
+                imeiInfoList.accept(ImeiInfoPreferenceController.DEFAULT_KEY + (1 + slotIndex));
+            }
         }
 
         EidStatus eidStatus = new EidStatus(slotSimStatus, context, executor);
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
index a5019f8..13c5989 100644
--- a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
@@ -23,6 +23,7 @@
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
+import android.util.Log;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.fragment.app.Fragment;
@@ -33,70 +34,80 @@
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
 import com.android.settings.deviceinfo.PhoneNumberSummaryPreference;
+import com.android.settings.deviceinfo.simstatus.SlotSimStatus;
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settingslib.Utils;
 
-import java.util.ArrayList;
-import java.util.List;
-
 /**
  * Controller that manages preference for single and multi sim devices.
  */
 public class ImeiInfoPreferenceController extends BasePreferenceController {
 
-    private static final String KEY_PREFERENCE_CATEGORY = "device_detail_category";
+    private static final String TAG = "ImeiInfoPreferenceController";
 
-    private final boolean mIsMultiSim;
-    private final TelephonyManager mTelephonyManager;
-    private final List<Preference> mPreferenceList = new ArrayList<>();
+    private static final String KEY_PREFERENCE_CATEGORY = "device_detail_category";
+    public static final String DEFAULT_KEY = "imei_info";
+
+    private TelephonyManager mTelephonyManager;
     private Fragment mFragment;
+    private SlotSimStatus mSlotSimStatus;
 
     public ImeiInfoPreferenceController(Context context, String key) {
         super(context, key);
-        mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
-        mIsMultiSim = mTelephonyManager.getPhoneCount() > 1;
     }
 
-    public void setHost(Fragment fragment) {
+    public void init(Fragment fragment, SlotSimStatus slotSimStatus) {
         mFragment = fragment;
+        mSlotSimStatus = slotSimStatus;
+    }
+
+    private boolean isMultiSim() {
+        return (mSlotSimStatus != null) && (mSlotSimStatus.size() > 1);
+    }
+
+    private int keyToSlotIndex(String key) {
+        int simSlot = SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+        try {
+            simSlot = Integer.valueOf(key.replace(DEFAULT_KEY, "")) - 1;
+        } catch (Exception exception) {
+            Log.i(TAG, "Invalid key : " + key);
+        }
+        return simSlot;
+    }
+
+    private SubscriptionInfo getSubscriptionInfo(int simSlot) {
+        return (mSlotSimStatus == null) ? null : mSlotSimStatus.getSubscriptionInfo(simSlot);
     }
 
     @Override
     public void displayPreference(PreferenceScreen screen) {
         super.displayPreference(screen);
-        if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+        if ((!SubscriptionUtil.isSimHardwareVisible(mContext)) || (mSlotSimStatus == null)) {
             return;
         }
-        final Preference preference = screen.findPreference(getPreferenceKey());
-        final PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY);
-
-        mPreferenceList.add(preference);
-        updatePreference(preference, 0 /* simSlot */);
-
-        final int imeiPreferenceOrder = preference.getOrder();
-        // Add additional preferences for each sim in the device
-        for (int simSlotNumber = 1; simSlotNumber < mTelephonyManager.getPhoneCount();
-                simSlotNumber++) {
-            final Preference multiSimPreference = createNewPreference(screen.getContext());
-            multiSimPreference.setCopyingEnabled(true);
-            multiSimPreference.setOrder(imeiPreferenceOrder + simSlotNumber);
-            multiSimPreference.setKey(getPreferenceKey() + simSlotNumber);
-            category.addPreference(multiSimPreference);
-            mPreferenceList.add(multiSimPreference);
-            updatePreference(multiSimPreference, simSlotNumber);
+        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
+        Preference preference = screen.findPreference(DEFAULT_KEY);
+        if (!isAvailable() || preference == null || !preference.isVisible()) {
+            return;
         }
+        PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY);
+
+        int imeiPreferenceOrder = preference.getOrder();
+        screen.removePreference(preference);
+        preference.setVisible(false);
+
+        // Add additional preferences for each imei slot in the device
+        for (int simSlotNumber = 0; simSlotNumber < mSlotSimStatus.size(); simSlotNumber++) {
+            Preference multiImeiPreference = createNewPreference(screen.getContext());
+            multiImeiPreference.setOrder(imeiPreferenceOrder + 1 + simSlotNumber);
+            multiImeiPreference.setKey(DEFAULT_KEY + (1 + simSlotNumber));
+            category.addPreference(multiImeiPreference);
+       }
     }
 
     @Override
     public void updateState(Preference preference) {
-        if (preference == null) {
-            return;
-        }
-        int size = mPreferenceList.size();
-        for (int i = 0; i < size; i++) {
-            Preference pref = mPreferenceList.get(i);
-            updatePreference(pref, i);
-        }
+        updatePreference(preference, keyToSlotIndex(preference.getKey()));
     }
 
     @Override
@@ -112,8 +123,8 @@
 
     @Override
     public boolean handlePreferenceTreeClick(Preference preference) {
-        final int simSlot = mPreferenceList.indexOf(preference);
-        if (simSlot == -1) {
+        final int simSlot = keyToSlotIndex(preference.getKey());
+        if (simSlot < 0) {
             return false;
         }
 
@@ -124,9 +135,10 @@
 
     @Override
     public int getAvailabilityStatus() {
-        return SubscriptionUtil.isSimHardwareVisible(mContext) &&
-                mContext.getSystemService(UserManager.class).isAdminUser()
-                && !Utils.isWifiOnly(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+        boolean isAvailable = SubscriptionUtil.isSimHardwareVisible(mContext) &&
+                mContext.getSystemService(UserManager.class).isAdminUser() &&
+                !Utils.isWifiOnly(mContext);
+        return isAvailable ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
     }
 
     @Override
@@ -135,29 +147,48 @@
     }
 
     private void updatePreference(Preference preference, int simSlot) {
+        SubscriptionInfo subInfo = getSubscriptionInfo(simSlot);
+        preference.setEnabled(subInfo != null);
+        preference.setCopyingEnabled(subInfo != null);
         preference.setTitle(getTitle(simSlot));
         preference.setSummary(getSummary());
     }
 
-    private CharSequence getTitleForGsmPhone(int simSlot) {
-        return mIsMultiSim ? mContext.getString(R.string.imei_multi_sim, simSlot + 1)
+    private CharSequence getTitleForGsmPhone(int simSlot, boolean isPrimaryImei) {
+        int titleId = isPrimaryImei ? R.string.imei_multi_sim_primary : R.string.imei_multi_sim;
+        return isMultiSim() ? mContext.getString(titleId, simSlot + 1)
                 : mContext.getString(R.string.status_imei);
     }
 
-    private CharSequence getTitleForCdmaPhone(int simSlot) {
-        return mIsMultiSim ? mContext.getString(R.string.meid_multi_sim, simSlot + 1)
+    private CharSequence getTitleForCdmaPhone(int simSlot, boolean isPrimaryImei) {
+        int titleId = isPrimaryImei ? R.string.meid_multi_sim_primary : R.string.meid_multi_sim;
+        return isMultiSim() ? mContext.getString(titleId, simSlot + 1)
                 : mContext.getString(R.string.status_meid_number);
     }
 
-    private CharSequence getTitle(int simSlot) {
-        final int phoneType = getPhoneType(simSlot);
-        return phoneType == PHONE_TYPE_CDMA ? getTitleForCdmaPhone(simSlot)
-                : getTitleForGsmPhone(simSlot);
+    protected boolean isPrimaryImei(int simSlot) {
+        CharSequence imei = getSummary(simSlot);
+        if (imei == null) {
+            return false;
+        }
+        String primaryImei = null;
+        try {
+            primaryImei = mTelephonyManager.getPrimaryImei();
+        } catch (Exception exception) {
+            Log.i(TAG, "PrimaryImei not available. " + exception);
+        }
+        return (primaryImei != null) && primaryImei.equals(imei.toString());
     }
 
-    private int getPhoneType(int slotIndex) {
-        SubscriptionInfo subInfo = SubscriptionManager.from(mContext)
-                .getActiveSubscriptionInfoForSimSlotIndex(slotIndex);
+    private CharSequence getTitle(int simSlot) {
+        boolean isPrimaryImei = isMultiSim() && isPrimaryImei(simSlot);
+        final int phoneType = getPhoneType(simSlot);
+        return phoneType == PHONE_TYPE_CDMA ? getTitleForCdmaPhone(simSlot, isPrimaryImei)
+                : getTitleForGsmPhone(simSlot, isPrimaryImei);
+    }
+
+    public int getPhoneType(int slotIndex) {
+        SubscriptionInfo subInfo = getSubscriptionInfo(slotIndex);
         return mTelephonyManager.getCurrentPhoneType(subInfo != null ? subInfo.getSubscriptionId()
                 : SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
     }
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
index f7970cf..f3a9358 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
@@ -18,10 +18,9 @@
 
 import static android.telephony.TelephonyManager.PHONE_TYPE_CDMA;
 import static android.telephony.TelephonyManager.PHONE_TYPE_GSM;
-
+import static android.telephony.TelephonyManager.PHONE_TYPE_NONE;
 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
-
-import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.spy;
@@ -32,15 +31,13 @@
 import android.content.res.Resources;
 import android.os.UserManager;
 import android.telephony.TelephonyManager;
-
 import androidx.fragment.app.Fragment;
 import androidx.fragment.app.FragmentManager;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceScreen;
-
 import com.android.settings.R;
-
+import com.android.settings.deviceinfo.simstatus.SlotSimStatus;
 import org.junit.Before;
 import org.junit.Ignore;
 import org.junit.Test;
@@ -50,7 +47,6 @@
 import org.mockito.MockitoAnnotations;
 import org.robolectric.RobolectricTestRunner;
 import org.robolectric.RuntimeEnvironment;
-import org.robolectric.util.ReflectionHelpers;
 
 @RunWith(RobolectricTestRunner.class)
 public class ImeiInfoPreferenceControllerTest {
@@ -72,7 +68,9 @@
 
     private Context mContext;
     private Resources mResources;
+    private ImeiInfoPreferenceController mDefaultController;
     private ImeiInfoPreferenceController mController;
+    private ImeiInfoPreferenceController mSecondController;
 
     @Before
     public void setUp() {
@@ -83,56 +81,77 @@
         when(mContext.getResources()).thenReturn(mResources);
         when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
 
-        doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
-        mController = spy(new ImeiInfoPreferenceController(mContext, "imei_info"));
-        mController.setHost(mFragment);
-        doReturn(AVAILABLE).when(mController).getAvailabilityStatus();
+        mockService(Context.TELEPHONY_SERVICE, TelephonyManager.class, mTelephonyManager);
+        mockService(Context.USER_SERVICE, UserManager.class, mUserManager);
+
         when(mScreen.getContext()).thenReturn(mContext);
-        doReturn(mSecondSimPreference).when(mController).createNewPreference(mContext);
         final String categoryKey = "device_detail_category";
         when(mScreen.findPreference(categoryKey)).thenReturn(mCategory);
-        ReflectionHelpers.setField(mController, "mTelephonyManager", mTelephonyManager);
-        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
-        final String prefKey = mController.getPreferenceKey();
-        when(mPreference.getKey()).thenReturn(prefKey);
-        when(mPreference.isVisible()).thenReturn(true);
     }
 
-    @Test
-    public void displayPreference_multiSimGsm_shouldAddSecondPreference() {
-        ReflectionHelpers.setField(mController, "mIsMultiSim", true);
-        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-        when(mTelephonyManager.getCurrentPhoneType(anyInt())).thenReturn(PHONE_TYPE_GSM);
+    private ImeiInfoPreferenceController createPreferenceController(SlotSimStatus slotSimStatus,
+        String key, Preference preference, int phoneType) {
+        ImeiInfoPreferenceController controller =
+                spy(new ImeiInfoPreferenceController(mContext, key) {
+                    public int getPhoneType(int slotId) {
+                        return phoneType;
+                    }
+                });
+        controller.init(mFragment, slotSimStatus);
+        doReturn(AVAILABLE).when(controller).getAvailabilityStatus();
+        doReturn(preference).when(controller).createNewPreference(mContext);
 
-        mController.displayPreference(mScreen);
+        when(mScreen.findPreference(key)).thenReturn(preference);
+        when(preference.getKey()).thenReturn(key);
+        when(preference.isVisible()).thenReturn(true);
+        return controller;
+    }
 
-        verify(mCategory).addPreference(mSecondSimPreference);
+    private void setupPhoneCount(int count, int phoneType1, int phoneType2) {
+        when(mTelephonyManager.getPhoneCount()).thenReturn(count);
+
+        SlotSimStatus slotSimStatus = new SlotSimStatus(mContext);
+        mController = createPreferenceController(slotSimStatus,
+                "imei_info1", mPreference, phoneType1);
+        mSecondController = createPreferenceController(slotSimStatus,
+                "imei_info2", mSecondSimPreference, phoneType2);
     }
 
     @Ignore
     @Test
+    public void displayPreference_multiSimGsm_shouldAddSecondPreference() {
+        setupPhoneCount(2, PHONE_TYPE_GSM, PHONE_TYPE_GSM);
+
+        mDefaultController.displayPreference(mScreen);
+
+        verify(mCategory).addPreference(mSecondSimPreference);
+    }
+
+    @Test
     public void displayPreference_singleSimCdmaPhone_shouldSetSingleSimCdmaTitleAndMeid() {
-        ReflectionHelpers.setField(mController, "mIsMultiSim", false);
-        final String meid = "125132215123";
-        when(mTelephonyManager.getCurrentPhoneType(anyInt())).thenReturn(PHONE_TYPE_CDMA);
+        setupPhoneCount(1, PHONE_TYPE_CDMA, PHONE_TYPE_NONE);
+
+        final String meid = "Tap to show info";
         when(mTelephonyManager.getMeid(anyInt())).thenReturn(meid);
 
         mController.displayPreference(mScreen);
+        mController.updateState(mPreference);
 
         verify(mPreference).setTitle(mContext.getString(R.string.status_meid_number));
         verify(mPreference).setSummary(meid);
     }
 
-    @Ignore
     @Test
     public void displayPreference_multiSimCdmaPhone_shouldSetMultiSimCdmaTitleAndMeid() {
-        ReflectionHelpers.setField(mController, "mIsMultiSim", true);
-        final String meid = "125132215123";
-        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-        when(mTelephonyManager.getCurrentPhoneType(anyInt())).thenReturn(PHONE_TYPE_CDMA);
+        setupPhoneCount(2, PHONE_TYPE_CDMA, PHONE_TYPE_CDMA);
+
+        final String meid = "Tap to show info";
         when(mTelephonyManager.getMeid(anyInt())).thenReturn(meid);
 
         mController.displayPreference(mScreen);
+        mController.updateState(mPreference);
+        mSecondController.displayPreference(mScreen);
+        mSecondController.updateState(mSecondSimPreference);
 
         verify(mPreference).setTitle(mContext.getString(R.string.meid_multi_sim, 1 /* sim slot */));
         verify(mSecondSimPreference).setTitle(
@@ -141,30 +160,31 @@
         verify(mSecondSimPreference).setSummary(meid);
     }
 
-    @Ignore
     @Test
     public void displayPreference_singleSimGsmPhone_shouldSetSingleSimGsmTitleAndImei() {
-        ReflectionHelpers.setField(mController, "mIsMultiSim", false);
-        final String imei = "125132215123";
-        when(mTelephonyManager.getCurrentPhoneType(anyInt())).thenReturn(PHONE_TYPE_GSM);
+        setupPhoneCount(1, PHONE_TYPE_GSM, PHONE_TYPE_NONE);
+
+        final String imei = "Tap to show info";
         when(mTelephonyManager.getImei(anyInt())).thenReturn(imei);
 
         mController.displayPreference(mScreen);
+        mController.updateState(mPreference);
 
         verify(mPreference).setTitle(mContext.getString(R.string.status_imei));
         verify(mPreference).setSummary(imei);
     }
 
-    @Ignore
     @Test
     public void displayPreference_multiSimGsmPhone_shouldSetMultiSimGsmTitleAndImei() {
-        ReflectionHelpers.setField(mController, "mIsMultiSim", true);
-        final String imei = "125132215123";
-        when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-        when(mTelephonyManager.getCurrentPhoneType(anyInt())).thenReturn(PHONE_TYPE_GSM);
+        setupPhoneCount(2, PHONE_TYPE_GSM, PHONE_TYPE_GSM);
+
+        final String imei = "Tap to show info";
         when(mTelephonyManager.getImei(anyInt())).thenReturn(imei);
 
         mController.displayPreference(mScreen);
+        mController.updateState(mPreference);
+        mSecondController.displayPreference(mScreen);
+        mSecondController.updateState(mSecondSimPreference);
 
         verify(mPreference).setTitle(mContext.getString(R.string.imei_multi_sim, 1 /* sim slot */));
         verify(mSecondSimPreference).setTitle(
@@ -175,6 +195,8 @@
 
     @Test
     public void handlePreferenceTreeClick_shouldStartDialogFragment() {
+        setupPhoneCount(1, PHONE_TYPE_GSM, PHONE_TYPE_NONE);
+
         when(mFragment.getChildFragmentManager())
                 .thenReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS));
         when(mPreference.getTitle()).thenReturn("SomeTitle");
@@ -184,4 +206,9 @@
 
         verify(mFragment).getChildFragmentManager();
     }
+
+    private <T> void mockService(String serviceName, Class<T> serviceClass, T service) {
+        when(mContext.getSystemServiceName(serviceClass)).thenReturn(serviceName);
+        when(mContext.getSystemService(serviceName)).thenReturn(service);
+    }
 }