Merge "[Sim UI enhancement] remove the "Tap to show info"" into main
diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml
index b5d0c59..a29e123 100644
--- a/res/xml/mobile_network_settings.xml
+++ b/res/xml/mobile_network_settings.xml
@@ -48,6 +48,23 @@
             settings:controller="com.android.settings.network.telephony.SmsDefaultSubscriptionController"/>
 
         <Preference
+            android:key="mobile_network_spn"
+            android:title="@string/mobile_network_spn_title"
+            android:summary="@string/summary_placeholder"
+            android:selectable="false"
+            settings:controller="com.android.settings.network.telephony.MobileNetworkSpnPreferenceController"
+            settings:allowDividerAbove="true" />
+
+        <Preference
+            android:key="phone_number"
+            android:title="@string/status_number"
+            android:summary="@string/summary_placeholder"
+            android:selectable="false"
+            settings:controller="com.android.settings.network.telephony.MobileNetworkPhoneNumberPreferenceController"
+            settings:allowDividerBelow="true"
+            settings:enableCopying="true"/>
+
+        <Preference
             android:key="cdma_lte_data_service_key"
             android:title="@string/cdma_lte_data_service"
             settings:controller="com.android.settings.network.telephony.DataServiceSetupPreferenceController"
@@ -162,6 +179,24 @@
             settings:controller="com.android.settings.network.telephony.CarrierSettingsVersionPreferenceController"
             settings:enableCopying="true"/>
 
+        <!-- IMEI -->
+        <Preference
+            android:key="network_mode_imei_info"
+            android:title="@string/status_imei"
+            android:summary="@string/summary_placeholder"
+            settings:keywords="@string/keywords_imei_info"
+            settings:enableCopying="true"
+            settings:controller="com.android.settings.network.telephony.MobileNetworkImeiPreferenceController"/>
+        <!-- EID -->
+        <com.android.settingslib.CustomDialogPreferenceCompat
+            android:key="network_mode_eid_info"
+            android:title="@string/status_eid"
+            android:summary="@string/device_info_protected_single_press"
+            android:positiveButtonText="@string/dlg_ok"
+            android:dialogLayout="@layout/dialog_eid_status"
+            settings:enableCopying="true"
+            settings:controller="com.android.settings.network.telephony.MobileNetworkEidPreferenceController"/>
+
         <PreferenceCategory
             android:key="calling_category"
             android:title="@string/call_category"
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index 378d9a1..ef74a2e 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -42,6 +42,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.datausage.DataUsageUtils;
+import com.android.settings.flags.Flags;
 import com.android.settings.network.MobileDataContentObserver;
 import com.android.settings.network.ProxySubscriptionManager;
 import com.android.settings.network.SubscriptionsChangeListener;
@@ -194,7 +195,8 @@
 
     @Override
     public int getAvailabilityStatus(int subId) {
-        if (!SubscriptionManager.isValidSubscriptionId(subId)
+        if (Flags.isDualSimOnboardingEnabled()
+                || !SubscriptionManager.isValidSubscriptionId(subId)
                 || SubscriptionManager.getDefaultDataSubscriptionId() == subId
                 || (!hasMobileData())) {
             return CONDITIONALLY_UNAVAILABLE;
diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java
index 206b3a9..03ce7f6 100644
--- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java
+++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java
@@ -32,6 +32,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
+import com.android.settings.flags.Flags;
 import com.android.settings.network.DefaultSubscriptionReceiver;
 import com.android.settings.network.MobileNetworkRepository;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -88,6 +89,9 @@
 
     @Override
     public int getAvailabilityStatus(int subId) {
+        if (Flags.isDualSimOnboardingEnabled()) {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
         return AVAILABLE;
     }
 
diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
index 06015d4..bec7ee7 100644
--- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
+++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java
@@ -34,6 +34,7 @@
 import androidx.preference.TwoStatePreference;
 
 import com.android.settings.R;
+import com.android.settings.flags.Flags;
 import com.android.settings.network.MobileNetworkRepository;
 import com.android.settings.wifi.WifiPickerTrackerHelper;
 import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -83,6 +84,9 @@
 
     @Override
     public int getAvailabilityStatus(int subId) {
+        if (Flags.isDualSimOnboardingEnabled()) {
+            return CONDITIONALLY_UNAVAILABLE;
+        }
         return subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID
                 ? AVAILABLE
                 : AVAILABLE_UNSEARCHABLE;
diff --git a/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
new file mode 100644
index 0000000..907bab1
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceController.kt
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.graphics.Bitmap
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import android.telephony.euicc.EuiccManager
+import android.text.TextUtils
+import android.util.Log
+import android.view.WindowManager
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.annotation.VisibleForTesting
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.deviceinfo.PhoneNumberUtil
+import com.android.settings.flags.Flags
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.CustomDialogPreferenceCompat
+import com.android.settingslib.Utils
+import com.android.settingslib.qrcode.QrCodeGenerator
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Preference controller for "EID"
+ */
+open class MobileNetworkEidPreferenceController(context: Context, key: String) :
+    TelephonyBasePreferenceController(context, key) {
+
+    private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
+    private lateinit var preference: CustomDialogPreferenceCompat
+    private lateinit var fragment: Fragment
+    private var coroutineScope: CoroutineScope? = null
+    private var title = String()
+    private var eid = String()
+
+    fun init(fragment: Fragment, subId: Int) {
+        this.fragment = fragment
+        lazyViewModel = fragment.viewModels()
+        mSubId = subId
+    }
+
+    override fun getAvailabilityStatus(subId: Int): Int = when {
+        !Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
+        SubscriptionManager.isValidSubscriptionId(subId)
+                && eid.isNotEmpty()
+                && mContext.userManager.isAdminUser -> AVAILABLE
+
+        else -> CONDITIONALLY_UNAVAILABLE
+    }
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preference = screen.findPreference(preferenceKey)!!
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        preference.isVisible = false
+
+        val viewModel by lazyViewModel
+        coroutineScope = viewLifecycleOwner.lifecycleScope
+        viewModel.subscriptionInfoListFlow
+            .map { subscriptionInfoList ->
+                subscriptionInfoList
+                    .firstOrNull { subInfo ->
+                        subInfo.subscriptionId == mSubId && subInfo.isEmbedded
+                    }
+            }
+            .collectLatestWithLifecycle(viewLifecycleOwner) { subscriptionInfo ->
+                subscriptionInfo?.let {
+                    coroutineScope?.launch {
+                        refreshData(it)
+                    }
+                }
+            }
+    }
+
+    @VisibleForTesting
+    suspend fun refreshData(subscriptionInfo: SubscriptionInfo) {
+        withContext(Dispatchers.Default) {
+            eid = getEid(subscriptionInfo)
+            if (eid.isEmpty()) {
+                Log.d(TAG, "EID is empty.")
+            }
+            title = getTitle()
+        }
+        refreshUi()
+    }
+
+    fun refreshUi() {
+        preference.title = title
+        preference.dialogTitle = title
+        preference.summary = eid
+        preference.isVisible = eid.isNotEmpty()
+    }
+
+    override fun handlePreferenceTreeClick(preference: Preference): Boolean {
+        if (preference.key != preferenceKey) return false
+        this.preference.setOnShowListener {
+            coroutineScope?.launch { updateDialog() }
+        }
+        return true
+    }
+
+    private fun getTitle(): String {
+        return mContext.getString(R.string.status_eid)
+    }
+
+    private suspend fun updateDialog() {
+        val dialog = preference.dialog ?: return
+        dialog.window?.setFlags(
+            WindowManager.LayoutParams.FLAG_SECURE,
+            WindowManager.LayoutParams.FLAG_SECURE
+        )
+        dialog.setCanceledOnTouchOutside(false)
+        val textView = dialog.requireViewById<TextView>(R.id.esim_id_value)
+        textView.text = PhoneNumberUtil.expandByTts(eid)
+
+        val qrCodeView = dialog.requireViewById<ImageView>(R.id.esim_id_qrcode)
+
+        qrCodeView.setImageBitmap(getEidQrCode(eid))
+    }
+
+    protected fun getTelephonyManager(context: Context): TelephonyManager? {
+        return context.getSystemService(TelephonyManager::class.java)
+    }
+
+    protected fun getEuiccManager(context: Context): EuiccManager? {
+        return context.getSystemService(EuiccManager::class.java)
+    }
+
+    @VisibleForTesting
+    fun getEid(subscriptionInfo: SubscriptionInfo): String {
+        val euiccMgr = getEuiccManager(mContext)
+        val telMgr = getTelephonyManager(mContext)
+        if(euiccMgr==null || telMgr==null) return String()
+
+        var eid = getEidPerSlot(telMgr, euiccMgr, subscriptionInfo)
+        return eid.ifEmpty {
+            getDefaultEid(euiccMgr)
+        }
+    }
+
+    private fun getEidPerSlot(
+        telMgr: TelephonyManager,
+        euiccMgr: EuiccManager,
+        subscriptionInfo: SubscriptionInfo
+    ): String {
+        val uiccCardInfoList = telMgr.uiccCardsInfo
+        val cardId = subscriptionInfo.cardId
+
+        /**
+         * Find EID from first slot which contains an eSIM and with card ID within
+         * the eSIM card ID provided by SubscriptionManager.
+         */
+        return uiccCardInfoList.firstOrNull { cardInfo -> cardInfo.isEuicc && cardInfo.cardId == cardId }
+            ?.let { cardInfo ->
+                var eid = cardInfo.getEid()
+                if (TextUtils.isEmpty(eid)) {
+                    eid = euiccMgr.createForCardId(cardInfo.cardId).getEid()
+                }
+                eid
+            } ?: String()
+    }
+
+    private fun getDefaultEid(euiccMgr: EuiccManager?): String {
+        return if (euiccMgr == null || !euiccMgr.isEnabled) {
+            String()
+        } else euiccMgr.getEid() ?: String()
+    }
+
+    companion object {
+        private const val TAG = "MobileNetworkEidPreferenceController"
+        private const val QR_CODE_SIZE = 600
+
+        /**
+         * Gets the QR code for EID
+         * @param eid is the EID string
+         * @return a Bitmap of QR code
+         */
+        private suspend fun getEidQrCode(eid: String): Bitmap? = withContext(Dispatchers.Default) {
+            try {
+                Log.d(TAG, "updateDialog. getEidQrCode $eid")
+                QrCodeGenerator.encodeQrCode(contents = eid, size = QR_CODE_SIZE)
+            } catch (exception: Exception) {
+                Log.w(TAG, "Error when creating QR code width $QR_CODE_SIZE", exception)
+                null
+            }
+        }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
new file mode 100644
index 0000000..8ec313b
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceController.kt
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.os.UserManager
+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
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.deviceinfo.imei.ImeiInfoDialogFragment
+import com.android.settings.flags.Flags
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.Utils
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Preference controller for "IMEI"
+ */
+class MobileNetworkImeiPreferenceController(context: Context, key: String) :
+    TelephonyBasePreferenceController(context, key) {
+
+    private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
+    private lateinit var preference: Preference
+    private lateinit var fragment: Fragment
+    private lateinit var mTelephonyManager: TelephonyManager
+    private var simSlot = -1
+    private var imei = String()
+    private var title = String()
+
+    fun init(fragment: Fragment, subId: Int) {
+        this.fragment = fragment
+        lazyViewModel = fragment.viewModels()
+        mSubId = subId
+        mTelephonyManager = mContext.getSystemService(TelephonyManager::class.java)
+            ?.createForSubscriptionId(mSubId)!!
+    }
+
+    override fun getAvailabilityStatus(subId: Int): Int = when {
+        !Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
+        SubscriptionManager.isValidSubscriptionId(subId)
+                && SubscriptionUtil.isSimHardwareVisible(mContext)
+                && mContext.userManager.isAdminUser
+                && !Utils.isWifiOnly(mContext) -> AVAILABLE
+        else -> CONDITIONALLY_UNAVAILABLE
+    }
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preference = screen.findPreference(preferenceKey)!!
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        val viewModel by lazyViewModel
+        val coroutineScope = viewLifecycleOwner.lifecycleScope
+
+        viewModel.subscriptionInfoListFlow
+                .collectLatestWithLifecycle(viewLifecycleOwner) { subscriptionInfoList ->
+                    subscriptionInfoList
+                            .firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
+                            ?.let {
+                                coroutineScope.launch {
+                                    refreshData(it)
+                                }
+                            }
+                }
+    }
+
+    @VisibleForTesting
+    suspend fun refreshData(subscription:SubscriptionInfo){
+        withContext(Dispatchers.Default) {
+            title = getTitle()
+            imei = getImei()
+            simSlot = subscription.simSlotIndex
+        }
+        refreshUi()
+    }
+
+    private fun refreshUi(){
+        preference.title = title
+        preference.summary = imei
+        preference.isVisible = true
+    }
+
+    override fun handlePreferenceTreeClick(preference: Preference): Boolean {
+        if (preference.key != preferenceKey) return false
+
+        Log.d(TAG, "handlePreferenceTreeClick:")
+        ImeiInfoDialogFragment.show(fragment, simSlot, preference.title.toString())
+        return true
+    }
+    private fun getImei(): String {
+        val phoneType = getPhoneType()
+        return if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) mTelephonyManager.meid?: String()
+                else mTelephonyManager.imei?: String()
+    }
+    private fun getTitleForGsmPhone(): String {
+        return mContext.getString(R.string.status_imei)
+    }
+
+    private fun getTitleForCdmaPhone(): String {
+        return mContext.getString(R.string.status_meid_number)
+    }
+
+    private fun getTitle(): String {
+        val phoneType = getPhoneType()
+        return if (phoneType == TelephonyManager.PHONE_TYPE_CDMA) getTitleForCdmaPhone()
+                else getTitleForGsmPhone()
+    }
+
+    fun getPhoneType(): Int {
+        return mTelephonyManager.currentPhoneType
+    }
+
+    companion object {
+        private const val TAG = "MobileNetworkImeiPreferenceController"
+    }
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
new file mode 100644
index 0000000..65a4b7e
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceController.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import androidx.annotation.VisibleForTesting
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+
+/**
+ * Preference controller for "Phone number"
+ */
+class MobileNetworkPhoneNumberPreferenceController(context: Context, key: String) :
+    TelephonyBasePreferenceController(context, key) {
+
+    private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
+    private lateinit var preference: Preference
+
+    private var phoneNumber = String()
+
+    fun init(fragment: Fragment, subId: Int) {
+        lazyViewModel = fragment.viewModels()
+        mSubId = subId
+    }
+
+    override fun getAvailabilityStatus(subId: Int): Int = when {
+        !Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
+        SubscriptionManager.isValidSubscriptionId(subId)
+                && SubscriptionUtil.isSimHardwareVisible(mContext) -> AVAILABLE
+        else -> CONDITIONALLY_UNAVAILABLE
+    }
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preference = screen.findPreference(preferenceKey)!!
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        val viewModel by lazyViewModel
+        val coroutineScope = viewLifecycleOwner.lifecycleScope
+
+        viewModel.subscriptionInfoListFlow
+            .map { subscriptionInfoList ->
+                subscriptionInfoList
+                    .firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
+            }
+            .flowOn(Dispatchers.Default)
+            .collectLatestWithLifecycle(viewLifecycleOwner) {
+                it?.let {
+                    coroutineScope.launch {
+                        refreshData(it)
+                    }
+                }
+            }
+    }
+
+    @VisibleForTesting
+    suspend fun refreshData(subscriptionInfo: SubscriptionInfo){
+        withContext(Dispatchers.Default) {
+            phoneNumber = getFormattedPhoneNumber(subscriptionInfo)
+        }
+        refreshUi()
+    }
+
+    private fun refreshUi(){
+        preference.summary = phoneNumber
+    }
+
+    private fun getFormattedPhoneNumber(subscriptionInfo: SubscriptionInfo?): String {
+        val phoneNumber = SubscriptionUtil.getBidiFormattedPhoneNumber(
+            mContext,
+            subscriptionInfo
+        )
+        return phoneNumber
+            ?.let { return it.ifEmpty { getStringUnknown() } }
+            ?: getStringUnknown()
+    }
+
+    private fun getStringUnknown(): String {
+        return mContext.getString(R.string.device_info_default)
+    }
+}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 4188f8d..2f2b20e 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -85,6 +85,7 @@
     private static final String KEY_SMS_PREF = "sms_preference";
     private static final String KEY_MOBILE_DATA_PREF = "mobile_data_enable";
     private static final String KEY_CONVERT_TO_ESIM_PREF = "convert_to_esim";
+    private static final String KEY_EID_KEY = "network_mode_eid_info";
 
     //String keys for preference lookup
     private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key";
@@ -171,6 +172,10 @@
                             String.valueOf(mSubId));
         });
 
+        MobileNetworkEidPreferenceController eid = new MobileNetworkEidPreferenceController(context,
+                KEY_EID_KEY);
+        eid.init(this, mSubId);
+
         return Arrays.asList(
                 new DataUsageSummaryPreferenceController(context, mSubId),
                 new RoamingPreferenceController(context, KEY_ROAMING_PREF, getSettingsLifecycle(),
@@ -182,7 +187,7 @@
                 new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF,
                         getSettingsLifecycle(), this, mSubId),
                 new ConvertToEsimPreferenceController(context, KEY_CONVERT_TO_ESIM_PREF,
-                        getSettingsLifecycle(), this, mSubId));
+                        getSettingsLifecycle(), this, mSubId), eid);
     }
 
     @Override
@@ -239,6 +244,10 @@
         use(DisableSimFooterPreferenceController.class).init(mSubId);
         use(NrDisabledInDsdsFooterPreferenceController.class).init(mSubId);
 
+        use(MobileNetworkSpnPreferenceController.class).init(this, mSubId);
+        use(MobileNetworkPhoneNumberPreferenceController.class).init(this, mSubId);
+        use(MobileNetworkImeiPreferenceController.class).init(this, mSubId);
+
         final MobileDataPreferenceController mobileDataPreferenceController =
                 use(MobileDataPreferenceController.class);
         if (mobileDataPreferenceController != null) {
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
new file mode 100644
index 0000000..ac055b0
--- /dev/null
+++ b/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceController.kt
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import androidx.annotation.VisibleForTesting
+import androidx.fragment.app.Fragment
+import androidx.fragment.app.viewModels
+import androidx.lifecycle.LifecycleOwner
+import androidx.preference.Preference
+import androidx.preference.PreferenceScreen
+import com.android.settings.flags.Flags
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
+
+/**
+ * Preference controller for "Mobile network" and showing the SPN.
+ */
+class MobileNetworkSpnPreferenceController(context: Context, key: String) :
+    TelephonyBasePreferenceController(context, key) {
+
+    private lateinit var lazyViewModel: Lazy<SubscriptionInfoListViewModel>
+    private lateinit var preference: Preference
+
+    private var spn = String()
+
+    fun init(fragment: Fragment, subId: Int) {
+        lazyViewModel = fragment.viewModels()
+        mSubId = subId
+    }
+
+    override fun getAvailabilityStatus(subId: Int): Int = when {
+        !Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
+        SubscriptionManager.isValidSubscriptionId(subId)-> AVAILABLE
+        else -> CONDITIONALLY_UNAVAILABLE
+    }
+
+    override fun displayPreference(screen: PreferenceScreen) {
+        super.displayPreference(screen)
+        preference = screen.findPreference(preferenceKey)!!
+    }
+
+    override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
+        val viewModel by lazyViewModel
+
+        viewModel.subscriptionInfoListFlow
+                .collectLatestWithLifecycle(viewLifecycleOwner) { subscriptionInfoList ->
+                    refreshData(subscriptionInfoList)
+                }
+    }
+
+    @VisibleForTesting
+    fun refreshData(subscriptionInfoList: List<SubscriptionInfo>){
+        spn = subscriptionInfoList
+            .firstOrNull { subInfo -> subInfo.subscriptionId == mSubId }
+            ?.let { info -> info.carrierName.toString() }
+            ?: String()
+
+        refreshUi()
+    }
+
+    private fun refreshUi(){
+        preference.summary = spn
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceControllerTest.kt
new file mode 100644
index 0000000..b035af5
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkEidPreferenceControllerTest.kt
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.platform.test.flag.junit.SetFlagsRule
+import android.telephony.SubscriptionInfo
+import android.telephony.TelephonyManager
+import android.telephony.euicc.EuiccManager
+import androidx.fragment.app.Fragment
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.flags.Flags
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.CustomDialogPreferenceCompat
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoSession
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
+
+@RunWith(AndroidJUnit4::class)
+class MobileNetworkEidPreferenceControllerTest {
+    @get:Rule val setFlagsRule: SetFlagsRule = SetFlagsRule()
+
+    private lateinit var mockSession: MockitoSession
+
+    private val mockViewModels =  mock<Lazy<SubscriptionInfoListViewModel>>()
+    private val mockFragment = mock<Fragment>{
+        val viewmodel = mockViewModels
+    }
+
+    private var mockEid = String()
+    private val mockTelephonyManager = mock<TelephonyManager> {
+        on {uiccCardsInfo} doReturn listOf()
+        on { createForSubscriptionId(any()) } doReturn mock
+    }
+    private val mockEuiccManager = mock<EuiccManager> {
+        on {isEnabled} doReturn true
+        on {eid} doReturn mockEid
+    }
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+        on { getSystemService(EuiccManager::class.java) } doReturn mockEuiccManager
+    }
+
+    private val controller = MobileNetworkEidPreferenceController(context, TEST_KEY)
+    private val preference = CustomDialogPreferenceCompat(context).apply { key = TEST_KEY }
+    private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+    @Before
+    fun setUp() {
+        mockSession = ExtendedMockito.mockitoSession()
+            .initMocks(this)
+            .mockStatic(SubscriptionUtil::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+
+        preferenceScreen.addPreference(preference)
+        controller.displayPreference(preferenceScreen)
+    }
+
+    @After
+    fun tearDown() {
+        mockSession.finishMocking()
+    }
+
+    @Test
+    fun refreshData_getEmptyEid_preferenceIsNotVisible() = runBlocking {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
+        whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
+            listOf(
+                SUB_INFO_1,
+                SUB_INFO_2
+            )
+        )
+        var mockSubId = 2
+        controller.init(mockFragment, mockSubId)
+        mockEid = String()
+
+        controller.refreshData(SUB_INFO_2)
+
+        assertThat(preference.isVisible).isEqualTo(false)
+    }
+
+    @Test
+    fun refreshData_getEmptyEid_preferenceSummaryIsExpected() = runBlocking {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
+        whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
+            listOf(
+                SUB_INFO_1,
+                SUB_INFO_2
+            )
+        )
+        var mockSubId = 2
+        controller.init(mockFragment, mockSubId)
+        mockEid = "test eid"
+        mockEuiccManager.stub {
+            on {eid} doReturn mockEid
+        }
+
+        controller.refreshData(SUB_INFO_2)
+
+        assertThat(preference.summary).isEqualTo(mockEid)
+    }
+
+    @Test
+    fun getAvailabilityStatus_notSimHardwareVisible() {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
+
+        val availabilityStatus = controller.availabilityStatus
+
+        assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val DISPLAY_NAME_1 = "Sub 1"
+        const val DISPLAY_NAME_2 = "Sub 2"
+
+        val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(1)
+            setDisplayName(DISPLAY_NAME_1)
+        }.build()
+
+        val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(2)
+            setDisplayName(DISPLAY_NAME_2)
+        }.build()
+
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceControllerTest.kt
new file mode 100644
index 0000000..2f67846
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkImeiPreferenceControllerTest.kt
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.TelephonyManager
+import android.telephony.euicc.EuiccManager
+import androidx.fragment.app.Fragment
+import androidx.preference.Preference
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.internal.telephony.PhoneConstants
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.android.settingslib.CustomDialogPreferenceCompat
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoSession
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
+
+@RunWith(AndroidJUnit4::class)
+class MobileNetworkImeiPreferenceControllerTest {
+    private lateinit var mockSession: MockitoSession
+
+    private val mockViewModels =  mock<Lazy<SubscriptionInfoListViewModel>>()
+    private val mockFragment = mock<Fragment>{
+        val viewmodel = mockViewModels
+    }
+
+    private var mockImei = String()
+    private val mockTelephonyManager = mock<TelephonyManager> {
+        on { uiccCardsInfo } doReturn listOf()
+        on { createForSubscriptionId(any()) } doReturn mock
+        on { currentPhoneType } doReturn TelephonyManager.PHONE_TYPE_GSM
+        on { imei } doReturn mockImei
+        on { meid } doReturn mockImei
+    }
+
+    private val context: Context = spy(ApplicationProvider.getApplicationContext()) {
+        on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+    }
+
+    private val controller = MobileNetworkImeiPreferenceController(context, TEST_KEY)
+    private val preference = Preference(context).apply { key = TEST_KEY }
+    private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+    @Before
+    fun setUp() {
+        mockSession = ExtendedMockito.mockitoSession()
+            .initMocks(this)
+            .mockStatic(SubscriptionUtil::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+
+        preferenceScreen.addPreference(preference)
+        controller.displayPreference(preferenceScreen)
+    }
+
+    @After
+    fun tearDown() {
+        mockSession.finishMocking()
+    }
+
+    @Test
+    fun refreshData_getPhoneNumber_preferenceSummaryIsExpected() = runBlocking {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
+        whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
+            listOf(
+                SUB_INFO_1,
+                SUB_INFO_2
+            )
+        )
+        var mockSubId = 2
+        controller.init(mockFragment, mockSubId)
+        mockImei = "test imei"
+        mockTelephonyManager.stub {
+            on { imei } doReturn mockImei
+        }
+
+        controller.refreshData(SUB_INFO_2)
+
+        assertThat(preference.summary).isEqualTo(mockImei)
+    }
+
+    @Test
+    fun getAvailabilityStatus_notSimHardwareVisible() {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
+
+        val availabilityStatus = controller.availabilityStatus
+
+        assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val DISPLAY_NAME_1 = "Sub 1"
+        const val DISPLAY_NAME_2 = "Sub 2"
+
+        val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(1)
+            setDisplayName(DISPLAY_NAME_1)
+        }.build()
+
+        val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(2)
+            setDisplayName(DISPLAY_NAME_2)
+        }.build()
+
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceControllerTest.kt
new file mode 100644
index 0000000..38c47c2
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkPhoneNumberPreferenceControllerTest.kt
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import androidx.fragment.app.Fragment
+import androidx.preference.Preference
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.settings.R
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoSession
+import org.mockito.kotlin.any
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
+
+@RunWith(AndroidJUnit4::class)
+class MobileNetworkPhoneNumberPreferenceControllerTest {
+    private lateinit var mockSession: MockitoSession
+
+    private val mockViewModels =  mock<Lazy<SubscriptionInfoListViewModel>>()
+    private val mockFragment = mock<Fragment>{
+        val viewmodel = mockViewModels
+    }
+
+    private var mockPhoneNumber = String()
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val controller = MobileNetworkPhoneNumberPreferenceController(context, TEST_KEY)
+    private val preference = Preference(context).apply { key = TEST_KEY }
+    private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+    @Before
+    fun setUp() {
+        mockSession = ExtendedMockito.mockitoSession()
+            .initMocks(this)
+            .mockStatic(SubscriptionUtil::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+
+        preferenceScreen.addPreference(preference)
+        controller.displayPreference(preferenceScreen)
+
+        whenever(SubscriptionUtil.getBidiFormattedPhoneNumber(any(),any())).thenReturn(mockPhoneNumber)
+    }
+
+    @After
+    fun tearDown() {
+        mockSession.finishMocking()
+    }
+
+    @Test
+    fun refreshData_getEmptyPhoneNumber_preferenceIsNotVisible() = runBlocking {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
+        whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
+            listOf(
+                SUB_INFO_1,
+                SUB_INFO_2
+            )
+        )
+        var mockSubId = 2
+        controller.init(mockFragment, mockSubId)
+        mockPhoneNumber = String()
+
+        controller.refreshData(SUB_INFO_2)
+
+        assertThat(preference.summary).isEqualTo(
+            context.getString(R.string.device_info_default))
+    }
+
+    @Test
+    fun refreshData_getPhoneNumber_preferenceSummaryIsExpected() = runBlocking {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
+        whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(
+            listOf(
+                SUB_INFO_1,
+                SUB_INFO_2
+            )
+        )
+        var mockSubId = 2
+        controller.init(mockFragment, mockSubId)
+        mockPhoneNumber = "test phone number"
+        whenever(SubscriptionUtil.getBidiFormattedPhoneNumber(any(),any())).thenReturn(mockPhoneNumber)
+
+        controller.refreshData(SUB_INFO_2)
+
+        assertThat(preference.summary).isEqualTo(mockPhoneNumber)
+    }
+
+    @Test
+    fun getAvailabilityStatus_notSimHardwareVisible() {
+        whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
+
+        val availabilityStatus = controller.availabilityStatus
+
+        assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val DISPLAY_NAME_1 = "Sub 1"
+        const val DISPLAY_NAME_2 = "Sub 2"
+
+        val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(1)
+            setDisplayName(DISPLAY_NAME_1)
+        }.build()
+
+        val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(2)
+            setDisplayName(DISPLAY_NAME_2)
+        }.build()
+
+    }
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceControllerTest.kt
new file mode 100644
index 0000000..f5592c1
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/MobileNetworkSpnPreferenceControllerTest.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.network.telephony
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.TelephonyManager
+import android.telephony.euicc.EuiccManager
+import androidx.fragment.app.Fragment
+import androidx.preference.Preference
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.dx.mockito.inline.extended.ExtendedMockito
+import com.android.settings.core.BasePreferenceController
+import com.android.settings.network.SubscriptionInfoListViewModel
+import com.android.settings.network.SubscriptionUtil
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.MockitoSession
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.whenever
+import org.mockito.quality.Strictness
+
+@RunWith(AndroidJUnit4::class)
+class MobileNetworkSpnPreferenceControllerTest {
+    private lateinit var mockSession: MockitoSession
+
+    private val mockViewModels =  mock<Lazy<SubscriptionInfoListViewModel>>()
+    private val mockFragment = mock<Fragment>{
+        val viewmodel = mockViewModels
+    }
+
+    private val context: Context = ApplicationProvider.getApplicationContext()
+    private val controller = MobileNetworkSpnPreferenceController(context, TEST_KEY)
+    private val preference = Preference(context).apply { key = TEST_KEY }
+    private val preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+    @Before
+    fun setUp() {
+        mockSession = ExtendedMockito.mockitoSession()
+            .initMocks(this)
+            .mockStatic(SubscriptionUtil::class.java)
+            .strictness(Strictness.LENIENT)
+            .startMocking()
+
+        preferenceScreen.addPreference(preference)
+        controller.displayPreference(preferenceScreen)
+    }
+
+    @After
+    fun tearDown() {
+        mockSession.finishMocking()
+    }
+
+    @Test
+    fun refreshData_getCarrierName_preferenceSummaryIsExpected() = runBlocking {
+        var testList = listOf(
+            SUB_INFO_1,
+            SUB_INFO_2
+        )
+        whenever(SubscriptionUtil.getActiveSubscriptions(any())).thenReturn(testList)
+        var mockSubId = 2
+        controller.init(mockFragment, mockSubId)
+
+        controller.refreshData(testList)
+
+        assertThat(preference.summary).isEqualTo(CARRIER_NAME_2)
+    }
+
+    private companion object {
+        const val TEST_KEY = "test_key"
+        const val CARRIER_NAME_1 = "Sub 1"
+        const val CARRIER_NAME_2 = "Sub 2"
+
+        val SUB_INFO_1: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(1)
+            setCarrierName(CARRIER_NAME_1)
+        }.build()
+
+        val SUB_INFO_2: SubscriptionInfo = SubscriptionInfo.Builder().apply {
+            setId(2)
+            setCarrierName(CARRIER_NAME_2)
+        }.build()
+
+    }
+}
diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
index 4d48025..11a490e 100644
--- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java
@@ -98,6 +98,7 @@
         doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE);
 
         when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
+        when(mSubscriptionManager.createForAllUserProfiles()).thenReturn(mSubscriptionManager);
         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(SUB_ID);
         doReturn(mInvalidTelephonyManager).when(mTelephonyManager).createForSubscriptionId(
                 SubscriptionManager.INVALID_SUBSCRIPTION_ID);
@@ -182,7 +183,8 @@
 
         mController.onPreferenceChange(mPreference, true);
 
-        verify(mTelephonyManager).setDataEnabled(true);
+        verify(mTelephonyManager).setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER
+                ,true);
     }
 
     @Test
@@ -195,7 +197,8 @@
 
         mController.onPreferenceChange(mPreference, true);
 
-        verify(mTelephonyManager).setDataEnabled(true);
+        verify(mTelephonyManager).setDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER
+                ,true);
     }
 
     @Test