Merge "Fix restriction to configure Calls & SMS" into main
diff --git a/res/drawable/ic_calls_sms.xml b/res/drawable/ic_calls_sms.xml
deleted file mode 100644
index 2033e8f..0000000
--- a/res/drawable/ic_calls_sms.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<!--
-    Copyright (C) 2020 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="24dp"
-    android:height="24dp"
-    android:viewportWidth="24"
-    android:viewportHeight="24"
-    android:tint="?android:attr/colorControlNormal"
-    >
-
-    <path
-        android:pathData="M 0 0 H 24 V 24 H 0 V 0 Z" />
-    <path
-        android:fillColor="#FF000000"
-        android:pathData="M20.17,14.85l-3.26-0.65c-0.33-0.07-0.67,0.04-0.9,0.27l-2.62,2.62c-2.75-1.49-5.01-3.75-6.5-6.5l2.62-2.62 c0.24-0.24,0.34-0.58,0.27-0.9L9.13,3.82c-0.09-0.47-0.5-0.8-0.98-0.8H4c-0.56,0-1.03,0.47-1,1.03c0.17,2.91,1.04,5.63,2.43,8.01 c1.57,2.69,3.81,4.93,6.5,6.5c2.38,1.39,5.1,2.26,8.01,2.43c0.56,0.03,1.03-0.44,1.03-1v-4.15C20.97,15.36,20.64,14.95,20.17,14.85 L20.17,14.85z M12,3v10l3-3h6V3H12z M19,8h-5V5h5V8z" />
-</vector>
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index ef6ed16..b055ea3 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -31,16 +31,11 @@
         settings:keywords="@string/keywords_internet"
         settings:useAdminDisabledSummary="true" />
 
-    <com.android.settingslib.RestrictedPreference
+    <com.android.settings.spa.preference.ComposePreference
         android:key="calls_and_sms"
         android:title="@string/calls_and_sms"
-        android:icon="@drawable/ic_calls_sms"
         android:order="-20"
-        android:summary="@string/summary_placeholder"
-        settings:isPreferenceVisible="@bool/config_show_sim_info"
-        settings:allowDividerBelow="true"
-        settings:keywords="@string/calls_and_sms"
-        settings:useAdminDisabledSummary="true" />
+        settings:controller="com.android.settings.network.NetworkProviderCallsSmsController" />
 
     <com.android.settingslib.RestrictedPreference
         android:key="mobile_network_list"
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index d558aa8..4790c65 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -22,7 +22,6 @@
 import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
-import android.provider.SearchIndexableResource;
 import android.util.Log;
 
 import androidx.appcompat.app.AlertDialog;
@@ -31,19 +30,16 @@
 
 import com.android.settings.R;
 import com.android.settings.SettingsDumpService;
-import com.android.settings.Utils;
 import com.android.settings.core.OnActivityResultListener;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.network.MobilePlanPreferenceController.MobilePlanPreferenceHost;
 import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.wifi.WifiPrimarySwitchPreferenceController;
 import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.search.SearchIndexable;
 
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 @SearchIndexable
@@ -122,7 +118,6 @@
             controllers.add(internetPreferenceController);
         }
         controllers.add(privateDnsPreferenceController);
-        controllers.add(new NetworkProviderCallsSmsController(context, lifecycle, lifecycleOwner));
 
         // Start SettingsDumpService after the MobileNetworkRepository is created.
         Intent intent = new Intent(context, SettingsDumpService.class);
diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsController.java b/src/com/android/settings/network/NetworkProviderCallsSmsController.java
deleted file mode 100644
index 5eec3d9..0000000
--- a/src/com/android/settings/network/NetworkProviderCallsSmsController.java
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-import static androidx.lifecycle.Lifecycle.Event;
-
-import android.content.Context;
-import android.os.UserManager;
-import android.telephony.ServiceState;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.util.Log;
-import android.view.View;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.lifecycle.LifecycleObserver;
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.OnLifecycleEvent;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settingslib.RestrictedPreference;
-import com.android.settingslib.Utils;
-import com.android.settingslib.core.AbstractPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
-
-import java.util.List;
-
-public class NetworkProviderCallsSmsController extends AbstractPreferenceController implements
-        LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback,
-        DefaultSubscriptionReceiver.DefaultSubscriptionListener {
-
-    private static final String TAG = "NetworkProviderCallsSmsController";
-    private static final String KEY = "calls_and_sms";
-    private static final String RTL_MARK = "\u200F";
-
-    private UserManager mUserManager;
-    private TelephonyManager mTelephonyManager;
-    private RestrictedPreference mPreference;
-    private boolean mIsRtlMode;
-    private LifecycleOwner mLifecycleOwner;
-    private MobileNetworkRepository mMobileNetworkRepository;
-    private List<SubscriptionInfoEntity> mSubInfoEntityList;
-    private int mDefaultVoiceSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    private int mDefaultSmsSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    private DefaultSubscriptionReceiver mDataSubscriptionChangedReceiver;
-
-    /**
-     * The summary text and click behavior of the "Calls & SMS" item on the
-     * Network & internet page.
-     */
-    public NetworkProviderCallsSmsController(Context context, Lifecycle lifecycle,
-            LifecycleOwner lifecycleOwner) {
-        super(context);
-
-        mUserManager = context.getSystemService(UserManager.class);
-        mTelephonyManager = mContext.getSystemService(TelephonyManager.class);
-        mIsRtlMode = context.getResources().getConfiguration().getLayoutDirection()
-                == View.LAYOUT_DIRECTION_RTL;
-        mLifecycleOwner = lifecycleOwner;
-        mMobileNetworkRepository = MobileNetworkRepository.getInstance(context);
-        mDataSubscriptionChangedReceiver = new DefaultSubscriptionReceiver(context, this);
-        if (lifecycle != null) {
-            lifecycle.addObserver(this);
-        }
-    }
-
-    @OnLifecycleEvent(Event.ON_RESUME)
-    public void onResume() {
-        mMobileNetworkRepository.addRegister(mLifecycleOwner, this,
-                SubscriptionManager.INVALID_SUBSCRIPTION_ID);
-        mMobileNetworkRepository.updateEntity();
-        mDataSubscriptionChangedReceiver.registerReceiver();
-        mDefaultVoiceSubId = SubscriptionManager.getDefaultVoiceSubscriptionId();
-        mDefaultSmsSubId = SubscriptionManager.getDefaultSmsSubscriptionId();
-    }
-
-    @OnLifecycleEvent(Event.ON_PAUSE)
-    public void onPause() {
-        mMobileNetworkRepository.removeRegister(this);
-        mDataSubscriptionChangedReceiver.unRegisterReceiver();
-    }
-
-    @Override
-    public void displayPreference(PreferenceScreen screen) {
-        super.displayPreference(screen);
-        mPreference = screen.findPreference(getPreferenceKey());
-    }
-
-    @Override
-    public CharSequence getSummary() {
-        List<SubscriptionInfoEntity> list = getSubscriptionInfoList();
-        if (list == null || list.isEmpty()) {
-            return setSummaryResId(R.string.calls_sms_no_sim);
-        } else {
-            final StringBuilder summary = new StringBuilder();
-            SubscriptionInfoEntity[] entityArray = list.toArray(
-                    new SubscriptionInfoEntity[0]);
-            for (SubscriptionInfoEntity subInfo : entityArray) {
-                int subsSize = list.size();
-                int subId = Integer.parseInt(subInfo.subId);
-                final CharSequence displayName = subInfo.uniqueName;
-
-                // Set displayName as summary if there is only one valid SIM.
-                if (subsSize == 1
-                        && list.get(0).isValidSubscription
-                        && isInService(subId)) {
-                    return displayName;
-                }
-
-                CharSequence status = getPreferredStatus(subInfo, subsSize, subId);
-                if (status.toString().isEmpty()) {
-                    // If there are 2 or more SIMs and one of these has no preferred status,
-                    // set only its displayName as summary.
-                    summary.append(displayName);
-                } else {
-                    summary.append(displayName)
-                            .append(" (")
-                            .append(status)
-                            .append(")");
-                }
-                // Do not add ", " for the last subscription.
-                if (list.size() > 0 && !subInfo.equals(list.get(list.size() - 1))) {
-                    summary.append(", ");
-                }
-
-                if (mIsRtlMode) {
-                    summary.insert(0, RTL_MARK).insert(summary.length(), RTL_MARK);
-                }
-            }
-            return summary;
-        }
-    }
-
-    @VisibleForTesting
-    protected CharSequence getPreferredStatus(SubscriptionInfoEntity subInfo, int subsSize,
-            int subId) {
-        String status = "";
-        boolean isCallPreferred = subInfo.getSubId() == getDefaultVoiceSubscriptionId();
-        boolean isSmsPreferred = subInfo.getSubId() == getDefaultSmsSubscriptionId();
-
-        if (!subInfo.isValidSubscription || !isInService(subId)) {
-            status = setSummaryResId(subsSize > 1 ? R.string.calls_sms_unavailable :
-                    R.string.calls_sms_temp_unavailable);
-        } else {
-            if (isCallPreferred && isSmsPreferred) {
-                status = setSummaryResId(R.string.calls_sms_preferred);
-            } else if (isCallPreferred) {
-                status = setSummaryResId(R.string.calls_sms_calls_preferred);
-            } else if (isSmsPreferred) {
-                status = setSummaryResId(R.string.calls_sms_sms_preferred);
-            }
-        }
-        return status;
-    }
-
-    private String setSummaryResId(int resId) {
-        return mContext.getResources().getString(resId);
-    }
-
-    @VisibleForTesting
-    protected List<SubscriptionInfoEntity> getSubscriptionInfoList() {
-        return mSubInfoEntityList;
-    }
-
-    private void update() {
-        if (mPreference == null || mPreference.isDisabledByAdmin()) {
-            return;
-        }
-        refreshSummary(mPreference);
-        mPreference.setOnPreferenceClickListener(null);
-        mPreference.setFragment(null);
-
-        if (mSubInfoEntityList == null || mSubInfoEntityList.isEmpty()) {
-            mPreference.setEnabled(false);
-        } else {
-            mPreference.setEnabled(true);
-            mPreference.setFragment(NetworkProviderCallsSmsFragment.class.getCanonicalName());
-        }
-    }
-
-    @Override
-    public boolean isAvailable() {
-        return SubscriptionUtil.isSimHardwareVisible(mContext) &&
-                mUserManager.isAdminUser();
-    }
-
-    @Override
-    public String getPreferenceKey() {
-        return KEY;
-    }
-
-    @Override
-    public void onAirplaneModeChanged(boolean airplaneModeEnabled) {
-        update();
-    }
-
-    @Override
-    public void updateState(Preference preference) {
-        super.updateState(preference);
-        if (preference == null) {
-            return;
-        }
-        refreshSummary(mPreference);
-        update();
-    }
-
-    @VisibleForTesting
-    protected boolean isInService(int subId) {
-        ServiceState serviceState =
-                mTelephonyManager.createForSubscriptionId(subId).getServiceState();
-        return Utils.isInService(serviceState);
-    }
-
-    @Override
-    public void onActiveSubInfoChanged(List<SubscriptionInfoEntity> activeSubInfoList) {
-        mSubInfoEntityList = activeSubInfoList;
-        update();
-    }
-
-    @VisibleForTesting
-    protected int getDefaultVoiceSubscriptionId() {
-        return mDefaultVoiceSubId;
-    }
-
-    @VisibleForTesting
-    protected int getDefaultSmsSubscriptionId() {
-        return mDefaultSmsSubId;
-    }
-
-    @Override
-    public void onDefaultVoiceChanged(int defaultVoiceSubId) {
-        mDefaultVoiceSubId = defaultVoiceSubId;
-        update();
-    }
-
-    @Override
-    public void onDefaultSmsChanged(int defaultSmsSubId) {
-        mDefaultSmsSubId = defaultSmsSubId;
-        update();
-    }
-}
diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsController.kt b/src/com/android/settings/network/NetworkProviderCallsSmsController.kt
new file mode 100644
index 0000000..a265041
--- /dev/null
+++ b/src/com/android/settings/network/NetworkProviderCallsSmsController.kt
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2023 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
+
+import android.app.settings.SettingsEnums
+import android.content.Context
+import android.content.IntentFilter
+import android.os.UserManager
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import androidx.annotation.VisibleForTesting
+import androidx.compose.foundation.layout.Column
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.outlined.PermPhoneMsg
+import androidx.compose.material3.HorizontalDivider
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.remember
+import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
+import androidx.lifecycle.viewmodel.compose.viewModel
+import com.android.settings.R
+import com.android.settings.core.SubSettingLauncher
+import com.android.settings.spa.preference.ComposePreferenceController
+import com.android.settingslib.Utils
+import com.android.settingslib.spa.widget.preference.PreferenceModel
+import com.android.settingslib.spa.widget.ui.SettingsIcon
+import com.android.settingslib.spaprivileged.framework.common.broadcastReceiverFlow
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.android.settingslib.spaprivileged.framework.compose.placeholder
+import com.android.settingslib.spaprivileged.model.enterprise.Restrictions
+import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+
+/**
+ * The summary text and click behavior of the "Calls & SMS" item on the Network & internet page.
+ */
+open class NetworkProviderCallsSmsController @JvmOverloads constructor(
+    context: Context,
+    preferenceKey: String,
+    private val getDisplayName: (SubscriptionInfo) -> CharSequence = { subInfo ->
+        SubscriptionUtil.getUniqueSubscriptionDisplayName(subInfo, context)
+    },
+    private val isInService: (Int) -> Boolean = IsInServiceImpl(context)::isInService,
+) : ComposePreferenceController(context, preferenceKey) {
+
+    override fun getAvailabilityStatus() = when {
+        !SubscriptionUtil.isSimHardwareVisible(mContext) -> UNSUPPORTED_ON_DEVICE
+        !mContext.userManager.isAdminUser -> DISABLED_FOR_USER
+        else -> AVAILABLE
+    }
+
+    @Composable
+    override fun Content() {
+        Column {
+            CallsAndSms()
+            HorizontalDivider()
+        }
+    }
+
+    @Composable
+    private fun CallsAndSms() {
+        val viewModel: SubscriptionInfoListViewModel = viewModel()
+        val subscriptionInfos by viewModel.subscriptionInfoListFlow.collectAsStateWithLifecycle()
+        val summary by remember { summaryFlow(viewModel.subscriptionInfoListFlow) }
+            .collectAsStateWithLifecycle(initialValue = placeholder())
+        RestrictedPreference(
+            model = object : PreferenceModel {
+                override val title = stringResource(R.string.calls_and_sms)
+                override val icon = @Composable { SettingsIcon(Icons.Outlined.PermPhoneMsg) }
+                override val summary = { summary }
+                override val enabled = { subscriptionInfos.isNotEmpty() }
+                override val onClick = {
+                    SubSettingLauncher(mContext).apply {
+                        setDestination(NetworkProviderCallsSmsFragment::class.qualifiedName)
+                        setSourceMetricsCategory(SettingsEnums.SETTINGS_NETWORK_CATEGORY)
+                    }.launch()
+                }
+            },
+            restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)),
+        )
+    }
+
+    private fun summaryFlow(subscriptionInfoListFlow: Flow<List<SubscriptionInfo>>) = combine(
+        subscriptionInfoListFlow,
+        mContext.defaultVoiceSubscriptionFlow(),
+        mContext.defaultSmsSubscriptionFlow(),
+        ::getSummary,
+    ).flowOn(Dispatchers.Default)
+
+    @VisibleForTesting
+    fun getSummary(
+        activeSubscriptionInfoList: List<SubscriptionInfo>,
+        defaultVoiceSubscriptionId: Int,
+        defaultSmsSubscriptionId: Int,
+    ): String {
+        if (activeSubscriptionInfoList.isEmpty()) {
+            return mContext.getString(R.string.calls_sms_no_sim)
+        }
+
+        activeSubscriptionInfoList.singleOrNull()?.let {
+            // Set displayName as summary if there is only one valid SIM.
+            if (isInService(it.subscriptionId)) return it.displayName.toString()
+        }
+
+        return activeSubscriptionInfoList.joinToString { subInfo ->
+            val displayName = getDisplayName(subInfo)
+
+            val subId = subInfo.subscriptionId
+            val statusResId = getPreferredStatus(
+                subId = subId,
+                subsSize = activeSubscriptionInfoList.size,
+                isCallPreferred = subId == defaultVoiceSubscriptionId,
+                isSmsPreferred = subId == defaultSmsSubscriptionId,
+            )
+            if (statusResId == null) {
+                // If there are 2 or more SIMs and one of these has no preferred status,
+                // set only its displayName as summary.
+                displayName
+            } else {
+                "$displayName (${mContext.getString(statusResId)})"
+            }
+        }
+    }
+
+    private fun getPreferredStatus(
+        subId: Int,
+        subsSize: Int,
+        isCallPreferred: Boolean,
+        isSmsPreferred: Boolean,
+    ): Int? = when {
+        !isInService(subId) -> {
+            if (subsSize > 1) {
+                R.string.calls_sms_unavailable
+            } else {
+                R.string.calls_sms_temp_unavailable
+            }
+        }
+
+        isCallPreferred && isSmsPreferred -> R.string.calls_sms_preferred
+        isCallPreferred -> R.string.calls_sms_calls_preferred
+        isSmsPreferred -> R.string.calls_sms_sms_preferred
+        else -> null
+    }
+}
+
+private fun Context.defaultVoiceSubscriptionFlow(): Flow<Int> =
+    merge(
+        flowOf(null), // kick an initial value
+        broadcastReceiverFlow(
+            IntentFilter(TelephonyManager.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED)
+        ),
+    ).map { SubscriptionManager.getDefaultVoiceSubscriptionId() }
+        .conflate().flowOn(Dispatchers.Default)
+
+private fun Context.defaultSmsSubscriptionFlow(): Flow<Int> =
+    merge(
+        flowOf(null), // kick an initial value
+        broadcastReceiverFlow(
+            IntentFilter(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED)
+        ),
+    ).map { SubscriptionManager.getDefaultSmsSubscriptionId() }
+        .conflate().flowOn(Dispatchers.Default)
+
+private class IsInServiceImpl(context: Context) {
+    private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
+
+    fun isInService(subId: Int): Boolean {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) return false
+
+        val serviceState = telephonyManager.createForSubscriptionId(subId).serviceState
+        return Utils.isInService(serviceState)
+    }
+}
diff --git a/src/com/android/settings/network/SubscriptionInfoListViewModel.kt b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
new file mode 100644
index 0000000..d30b21d
--- /dev/null
+++ b/src/com/android/settings/network/SubscriptionInfoListViewModel.kt
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2023 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
+
+import android.app.Application
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.plus
+
+class SubscriptionInfoListViewModel(application: Application) : AndroidViewModel(application) {
+    private val scope = viewModelScope + Dispatchers.Default
+
+    val subscriptionInfoListFlow = callbackFlow<List<SubscriptionInfo>> {
+        val subscriptionManager = application.getSystemService(SubscriptionManager::class.java)!!
+
+        val listener = object : SubscriptionManager.OnSubscriptionsChangedListener() {
+            override fun onSubscriptionsChanged() {
+                trySend(subscriptionManager.activeSubscriptionInfoList ?: emptyList())
+            }
+        }
+
+        subscriptionManager.addOnSubscriptionsChangedListener(
+            Dispatchers.Default.asExecutor(),
+            listener,
+        )
+
+        awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(listener) }
+    }.conflate().stateIn(scope, SharingStarted.Eagerly, initialValue = emptyList())
+}
diff --git a/tests/spa_unit/src/com/android/settings/network/NetworkProviderCallsSmsControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/NetworkProviderCallsSmsControllerTest.kt
new file mode 100644
index 0000000..110fd5e
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/NetworkProviderCallsSmsControllerTest.kt
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2023 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
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class NetworkProviderCallsSmsControllerTest {
+    private val context: Context = ApplicationProvider.getApplicationContext()
+
+    private var isInService: (Int) -> Boolean = { true }
+
+    private val controller = NetworkProviderCallsSmsController(
+        context = context,
+        preferenceKey = TEST_KEY,
+        getDisplayName = { subInfo -> subInfo.displayName },
+        isInService = { isInService(it) },
+    )
+
+    @Test
+    fun getSummary_noSim_returnNoSim() {
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = emptyList(),
+            defaultVoiceSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            defaultSmsSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+        )
+
+        assertThat(summary).isEqualTo(context.getString(R.string.calls_sms_no_sim))
+    }
+
+    @Test
+    fun getSummary_invalidSubId_returnUnavailable() {
+        isInService = { false }
+
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1),
+            defaultVoiceSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            defaultSmsSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+        )
+
+        assertThat(summary).isEqualTo("Sub 1 (Temporarily unavailable)")
+    }
+
+    @Test
+    fun getSummary_oneIsInvalidSubIdTwoIsValidSubId_returnOneIsUnavailable() {
+        isInService = { it == SUB_INFO_2.subscriptionId }
+
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2),
+            defaultVoiceSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            defaultSmsSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+        )
+
+        assertThat(summary).isEqualTo("Sub 1 (unavailable), Sub 2")
+    }
+
+    @Test
+    fun getSummary_oneSubscription_returnDisplayName() {
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1),
+            defaultVoiceSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            defaultSmsSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+        )
+
+        assertThat(summary).isEqualTo(DISPLAY_NAME_1)
+    }
+
+    @Test
+    fun getSummary_allSubscriptionsHaveNoPreferredStatus_returnDisplayName() {
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2),
+            defaultVoiceSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+            defaultSmsSubscriptionId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
+        )
+
+        assertThat(summary).isEqualTo("Sub 1, Sub 2")
+    }
+
+    @Test
+    fun getSummary_oneSubscriptionsIsCallPreferredTwoIsSmsPreferred_returnStatus() {
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2),
+            defaultVoiceSubscriptionId = SUB_INFO_1.subscriptionId,
+            defaultSmsSubscriptionId = SUB_INFO_2.subscriptionId,
+        )
+
+        assertThat(summary).isEqualTo("Sub 1 (preferred for calls), Sub 2 (preferred for SMS)")
+    }
+
+    @Test
+    fun getSummary_oneSubscriptionsIsSmsPreferredTwoIsCallPreferred_returnStatus() {
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2),
+            defaultVoiceSubscriptionId = SUB_INFO_2.subscriptionId,
+            defaultSmsSubscriptionId = SUB_INFO_1.subscriptionId,
+        )
+
+        assertThat(summary).isEqualTo("Sub 1 (preferred for SMS), Sub 2 (preferred for calls)")
+    }
+
+    @Test
+    fun getSummary_oneSubscriptionsIsSmsPreferredAndIsCallPreferred_returnStatus() {
+        val summary = controller.getSummary(
+            activeSubscriptionInfoList = listOf(SUB_INFO_1, SUB_INFO_2),
+            defaultVoiceSubscriptionId = SUB_INFO_1.subscriptionId,
+            defaultSmsSubscriptionId = SUB_INFO_1.subscriptionId,
+        )
+
+        assertThat(summary).isEqualTo("Sub 1 (preferred), Sub 2")
+    }
+
+    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/unit/src/com/android/settings/network/NetworkProviderCallsSmsControllerTest.java b/tests/unit/src/com/android/settings/network/NetworkProviderCallsSmsControllerTest.java
deleted file mode 100644
index 51aecc5..0000000
--- a/tests/unit/src/com/android/settings/network/NetworkProviderCallsSmsControllerTest.java
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- * Copyright (C) 2020 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;
-
-import static androidx.lifecycle.Lifecycle.Event;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.testutils.ResourcesUtils;
-import com.android.settingslib.RestrictedPreference;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-@RunWith(AndroidJUnit4.class)
-public class NetworkProviderCallsSmsControllerTest {
-
-    private static final String SUB_ID_1 = "1";
-    private static final String SUB_ID_2 = "2";
-    private static final String INVALID_SUB_ID = "-1";
-    private static final String KEY_PREFERENCE_CALLS_SMS = "calls_and_sms";
-    private static final String DISPLAY_NAME_1 = "Sub 1";
-    private static final String DISPLAY_NAME_2 = "Sub 2";
-    private static final String SUB_MCC_1 = "123";
-    private static final String SUB_MNC_1 = "456";
-    private static final String SUB_MCC_2 = "223";
-    private static final String SUB_MNC_2 = "456";
-    private static final String SUB_COUNTRY_ISO_1 = "Sub 1";
-    private static final String SUB_COUNTRY_ISO_2 = "Sub 2";
-
-    @Mock
-    private SubscriptionInfoEntity mSubInfo1;
-    @Mock
-    private SubscriptionInfoEntity mSubInfo2;
-    @Mock
-    private Lifecycle mLifecycle;
-    @Mock
-    private LifecycleOwner mLifecycleOwner;
-
-    private LifecycleRegistry mLifecycleRegistry;
-    private MockNetworkProviderCallsSmsController mController;
-    private PreferenceManager mPreferenceManager;
-    private PreferenceScreen mPreferenceScreen;
-    private RestrictedPreference mPreference;
-    private Context mContext;
-    private List<SubscriptionInfoEntity> mSubscriptionInfoEntityList = new ArrayList<>();
-
-    /**
-     * Mock the NetworkProviderCallsSmsController that allows one to set a default voice
-     * and SMS subscription ID.
-     */
-    private class MockNetworkProviderCallsSmsController extends
-            com.android.settings.network.NetworkProviderCallsSmsController {
-        public MockNetworkProviderCallsSmsController(Context context, Lifecycle lifecycle,
-                LifecycleOwner lifecycleOwner) {
-            super(context, lifecycle, lifecycleOwner);
-        }
-
-        private List<SubscriptionInfoEntity> mSubscriptionInfoEntity;
-        private boolean mIsInService;
-        private int mDefaultVoiceSubscriptionId;
-        private int mDefaultSmsSubscriptionId;
-
-        @Override
-        protected List<SubscriptionInfoEntity> getSubscriptionInfoList() {
-            return mSubscriptionInfoEntity;
-        }
-
-        public void setSubscriptionInfoList(List<SubscriptionInfoEntity> list) {
-            mSubscriptionInfoEntity = list;
-        }
-
-        @Override
-        protected boolean isInService(int subId) {
-            return mIsInService;
-        }
-
-        public void setInService(boolean inService) {
-            mIsInService = inService;
-        }
-
-        @Override
-        protected int getDefaultVoiceSubscriptionId() {
-            return mDefaultVoiceSubscriptionId;
-        }
-
-        @Override
-        protected int getDefaultSmsSubscriptionId() {
-            return mDefaultSmsSubscriptionId;
-        }
-
-        public void setDefaultVoiceSubscriptionId(int subscriptionId) {
-            mDefaultVoiceSubscriptionId = subscriptionId;
-        }
-
-        public void setDefaultSmsSubscriptionId(int subscriptionId) {
-            mDefaultSmsSubscriptionId = subscriptionId;
-        }
-    }
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mContext = spy(ApplicationProvider.getApplicationContext());
-
-        if (Looper.myLooper() == null) {
-            Looper.prepare();
-        }
-
-        mPreferenceManager = new PreferenceManager(mContext);
-        mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
-        mPreference = new RestrictedPreference(mContext);
-        mPreference.setKey(KEY_PREFERENCE_CALLS_SMS);
-        mController = new MockNetworkProviderCallsSmsController(mContext, mLifecycle,
-                mLifecycleOwner);
-        mController.setInService(true);
-        mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner);
-        when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry);
-    }
-
-    private void displayPreferenceWithLifecycle() {
-        mLifecycleRegistry.addObserver(mController);
-        mPreferenceScreen.addPreference(mPreference);
-        mController.displayPreference(mPreferenceScreen);
-        mLifecycleRegistry.handleLifecycleEvent(Event.ON_RESUME);
-    }
-
-    private String setSummaryResId(String resName) {
-        return ResourcesUtils.getResourcesString(mContext, resName);
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_noSim_returnNoSim() {
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        assertTrue(TextUtils.equals(mController.getSummary(),
-                setSummaryResId("calls_sms_no_sim")));
-    }
-
-    private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, int slotId,
-            int carrierId, String displayName, String mcc, String mnc, String countryIso,
-            int cardId, boolean isValid, boolean isActive, boolean isAvailable) {
-        return new SubscriptionInfoEntity(subId, slotId, carrierId,
-                displayName, displayName, 0, mcc, mnc, countryIso, false, cardId,
-                TelephonyManager.DEFAULT_PORT_INDEX, false, null,
-                SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false,
-                "1234567890", true, false, isValid,
-                true, isActive, isAvailable, false);
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_invalidSubId_returnUnavailable() {
-
-        mSubInfo1 = setupSubscriptionInfoEntity(INVALID_SUB_ID,
-                SubscriptionManager.INVALID_SIM_SLOT_INDEX, TelephonyManager.UNKNOWN_CARRIER_ID,
-                DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1, SUB_COUNTRY_ISO_1,
-                TelephonyManager.UNINITIALIZED_CARD_ID, false, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        final StringBuilder summary = new StringBuilder();
-        summary.append(DISPLAY_NAME_1)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_temp_unavailable"))
-                .append(")");
-
-        assertTrue(TextUtils.equals(mController.getSummary(), summary));
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_oneIsInvalidSubIdTwoIsValidSubId_returnOneIsUnavailable() {
-
-        mSubInfo1 = setupSubscriptionInfoEntity(INVALID_SUB_ID,
-                SubscriptionManager.INVALID_SIM_SLOT_INDEX, TelephonyManager.UNKNOWN_CARRIER_ID,
-                DISPLAY_NAME_1, SUB_MCC_1, SUB_MNC_1, SUB_COUNTRY_ISO_1,
-                TelephonyManager.UNINITIALIZED_CARD_ID, false, true, true);
-        mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 1, 1, DISPLAY_NAME_2, SUB_MCC_2,
-                SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, true, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mSubscriptionInfoEntityList.add(mSubInfo2);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        final StringBuilder summary = new StringBuilder();
-        summary.append(DISPLAY_NAME_1)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_unavailable"))
-                .append(")")
-                .append(", ")
-                .append(DISPLAY_NAME_2);
-
-        assertTrue(TextUtils.equals(mController.getSummary(), summary));
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_oneSubscription_returnDisplayName() {
-
-        mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
-                SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        assertThat(mPreference.getSummary()).isEqualTo(DISPLAY_NAME_1);
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_allSubscriptionsHaveNoPreferredStatus_returnDisplayName() {
-
-        mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
-                SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
-        mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 1, 1, DISPLAY_NAME_2, SUB_MCC_2,
-                SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, true, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mSubscriptionInfoEntityList.add(mSubInfo2);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        final StringBuilder summary = new StringBuilder();
-        summary.append(DISPLAY_NAME_1).append(", ").append(DISPLAY_NAME_2);
-
-        assertTrue(TextUtils.equals(mController.getSummary(), summary));
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_oneSubscriptionsIsCallPreferredTwoIsSmsPreferred_returnStatus() {
-
-        mController.setDefaultVoiceSubscriptionId(Integer.parseInt(SUB_ID_1));
-        mController.setDefaultSmsSubscriptionId(Integer.parseInt(SUB_ID_2));
-
-        mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
-                SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
-        mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 1, 1, DISPLAY_NAME_2, SUB_MCC_2,
-                SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, true, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mSubscriptionInfoEntityList.add(mSubInfo2);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        final StringBuilder summary = new StringBuilder();
-        summary.append(DISPLAY_NAME_1)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_calls_preferred"))
-                .append(")")
-                .append(", ")
-                .append(DISPLAY_NAME_2)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_sms_preferred"))
-                .append(")");
-
-        assertTrue(TextUtils.equals(mController.getSummary(), summary));
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_oneSubscriptionsIsSmsPreferredTwoIsCallPreferred_returnStatus() {
-
-        mController.setDefaultSmsSubscriptionId(Integer.parseInt(SUB_ID_1));
-        mController.setDefaultVoiceSubscriptionId(Integer.parseInt(SUB_ID_2));
-
-        mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
-                SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
-        mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 2, 2, DISPLAY_NAME_2, SUB_MCC_2,
-                SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, true, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mSubscriptionInfoEntityList.add(mSubInfo2);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        final StringBuilder summary = new StringBuilder();
-        summary.append(DISPLAY_NAME_1)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_sms_preferred"))
-                .append(")")
-                .append(", ")
-                .append(DISPLAY_NAME_2)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_calls_preferred"))
-                .append(")");
-
-        assertTrue(TextUtils.equals(mController.getSummary(), summary));
-    }
-
-    @Test
-    @UiThreadTest
-    public void getSummary_oneSubscriptionsIsSmsPreferredAndIsCallPreferred_returnStatus() {
-
-        mController.setDefaultSmsSubscriptionId(Integer.parseInt(SUB_ID_1));
-        mController.setDefaultVoiceSubscriptionId(Integer.parseInt(SUB_ID_1));
-
-        mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, 1, 1, DISPLAY_NAME_1, SUB_MCC_1,
-                SUB_MNC_1, SUB_COUNTRY_ISO_1, 1, true, true, true);
-        mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, 1, 1, DISPLAY_NAME_2, SUB_MCC_2,
-                SUB_MNC_2, SUB_COUNTRY_ISO_2, 1, true, true, true);
-        mSubscriptionInfoEntityList.add(mSubInfo1);
-        mSubscriptionInfoEntityList.add(mSubInfo2);
-        mController.setSubscriptionInfoList(mSubscriptionInfoEntityList);
-        displayPreferenceWithLifecycle();
-
-        final StringBuilder summary = new StringBuilder();
-        summary.append(DISPLAY_NAME_1)
-                .append(" (")
-                .append(setSummaryResId("calls_sms_preferred"))
-                .append(")")
-                .append(", ")
-                .append(DISPLAY_NAME_2);
-
-        assertTrue(TextUtils.equals(mController.getSummary(), summary));
-    }
-}