Setup backup calling for new UI

Backup calling new handles by CrossSimCallingViewModel.
CrossSimCallingViewModel keep monitoring the active SIMs, and setup
backup calling if needed.

Fix: 340444839
Test: manual - SIMs
Test: manual - Mobile Settings
Test: unit test
Change-Id: I0a3451f1e8c3984b2348cf628fb1d91ce7aaecec
diff --git a/src/com/android/settings/network/MobileDataEnabledFlow.kt b/src/com/android/settings/network/MobileDataEnabledFlow.kt
index 2342377..1f995a9 100644
--- a/src/com/android/settings/network/MobileDataEnabledFlow.kt
+++ b/src/com/android/settings/network/MobileDataEnabledFlow.kt
@@ -28,8 +28,8 @@
  *
  * Note: This flow can only notify enabled status changes, cannot provide the latest status.
  */
-fun Context.mobileDataEnabledFlow(subId: Int): Flow<Unit> {
-    val flow = settingsGlobalChangeFlow(Settings.Global.MOBILE_DATA)
+fun Context.mobileDataEnabledFlow(subId: Int, sendInitialValue: Boolean = true): Flow<Unit> {
+    val flow = settingsGlobalChangeFlow(Settings.Global.MOBILE_DATA, sendInitialValue)
     return when (subId) {
         SubscriptionManager.INVALID_SUBSCRIPTION_ID -> flow
         else -> {
diff --git a/src/com/android/settings/network/ProxySubscriptionManager.java b/src/com/android/settings/network/ProxySubscriptionManager.java
index 7e276e8..614491a 100644
--- a/src/com/android/settings/network/ProxySubscriptionManager.java
+++ b/src/com/android/settings/network/ProxySubscriptionManager.java
@@ -28,7 +28,6 @@
 import android.util.Log;
 
 import androidx.annotation.Keep;
-import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleObserver;
@@ -243,15 +242,6 @@
     }
 
     /**
-     * Gets a list of active, visible subscription Id(s) of the currently active SIM(s).
-     *
-     * @return the list of subId's that are active and visible; the length may be 0.
-     */
-    public @NonNull int[] getActiveSubscriptionIdList() {
-        return mSubscriptionMonitor.getActiveSubscriptionIdList();
-    }
-
-    /**
      * Clear data cached within proxy
      */
     public void clearCache() {
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index ef74a2e..fcbfdef 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -19,20 +19,14 @@
 import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
 import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
 
-import android.app.settings.SettingsEnums;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.PersistableBundle;
-import android.telephony.CarrierConfigManager;
 import android.telephony.SubscriptionManager;
 import android.telephony.TelephonyManager;
-import android.telephony.ims.ImsException;
-import android.telephony.ims.ImsManager;
-import android.telephony.ims.ImsMmTelManager;
-import android.util.Log;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 import androidx.lifecycle.LifecycleObserver;
 import androidx.lifecycle.OnLifecycleEvent;
 import androidx.preference.Preference;
@@ -40,15 +34,11 @@
 import androidx.preference.TwoStatePreference;
 
 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;
-import com.android.settings.network.ims.WifiCallingQueryImsState;
-import com.android.settings.overlay.FeatureFactory;
-import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
+import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel;
 
 /**
  * Controls whether switch mobile data to the non-default SIM if the non-default SIM has better
@@ -63,25 +53,29 @@
 public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenceController
         implements LifecycleObserver,
         SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
-    private static final String LOG_TAG = "AutoDataSwitchPrefCtrl";
 
+    @Nullable
     private TwoStatePreference mPreference;
+    @Nullable
     private SubscriptionsChangeListener mChangeListener;
+    @Nullable
     private TelephonyManager mManager;
+    @Nullable
     private MobileDataContentObserver mMobileDataContentObserver;
+    @Nullable
+    private CrossSimCallingViewModel mCrossSimCallingViewModel;
+    @Nullable
     private PreferenceScreen mScreen;
 
-    private final MetricsFeatureProvider mMetricsFeatureProvider;
-
-    public AutoDataSwitchPreferenceController(Context context,
-            String preferenceKey) {
+    public AutoDataSwitchPreferenceController(
+            @NonNull Context context, @NonNull String preferenceKey) {
         super(context, preferenceKey);
-        mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
     }
 
-    void init(int subId) {
+    void init(int subId, @Nullable CrossSimCallingViewModel crossSimCallingViewModel) {
         this.mSubId = subId;
         mManager = mContext.getSystemService(TelephonyManager.class).createForSubscriptionId(subId);
+        mCrossSimCallingViewModel = crossSimCallingViewModel;
     }
 
     @OnLifecycleEvent(ON_RESUME)
@@ -121,35 +115,15 @@
                 TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
     }
 
-    private int getOtherSubId(@NonNull int[] subIds) {
-        if (subIds.length > 1) {
-            for (int subId : subIds) {
-                if (subId != mSubId) {
-                    return subId;
-                }
-            }
-        }
-        return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
-    }
-
-    private boolean isEnabled(int subId) {
-        if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
-            return false;
-        }
-        TelephonyManager telephonyManager = mContext.getSystemService(
-                TelephonyManager.class).createForSubscriptionId(subId);
-        return telephonyManager != null && telephonyManager.isMobileDataPolicyEnabled(
-                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
-    }
-
     @Override
     public boolean setChecked(boolean isChecked) {
-        mManager.setMobileDataPolicyEnabled(
-                TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
-                isChecked);
-        if (mContext.getResources().getBoolean(
-                R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
-            trySetCrossSimCalling(mContext, getActiveSubscriptionIdList(), isChecked /* enabled */);
+        if (mManager != null) {
+            mManager.setMobileDataPolicyEnabled(
+                    TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
+                    isChecked);
+        }
+        if (mCrossSimCallingViewModel != null) {
+            mCrossSimCallingViewModel.updateCrossSimCalling();
         }
         return true;
     }
@@ -159,40 +133,6 @@
         return DataUsageUtils.hasMobileData(mContext);
     }
 
-    private boolean isCrossSimCallingAllowedByPlatform(Context context, int subId) {
-        if ((new WifiCallingQueryImsState(context, subId)).isWifiCallingSupported()) {
-            PersistableBundle bundle = getCarrierConfigForSubId(subId);
-            return (bundle != null) && bundle.getBoolean(
-                    CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
-                    false /*default*/);
-        }
-        return false;
-    }
-
-    protected ImsMmTelManager getImsMmTelManager(Context context, int subId) {
-        ImsManager imsMgr = context.getSystemService(ImsManager.class);
-        return (imsMgr == null) ? null : imsMgr.getImsMmTelManager(subId);
-    }
-
-    private void trySetCrossSimCallingPerSub(Context context, int subId, boolean enabled) {
-        try {
-            getImsMmTelManager(context, subId).setCrossSimCallingEnabled(enabled);
-        } catch (ImsException | IllegalArgumentException | NullPointerException exception) {
-            Log.w(LOG_TAG, "failed to change cross SIM calling configuration to " + enabled
-                    + " for subID " + subId + "with exception: ", exception);
-        }
-    }
-
-    private void trySetCrossSimCalling(Context context, int[] subIds, boolean enabled) {
-        mMetricsFeatureProvider.action(mContext,
-                SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT, enabled);
-        for (int subId : subIds) {
-            if (isCrossSimCallingAllowedByPlatform(context, subId)) {
-                trySetCrossSimCallingPerSub(context, subId, enabled);
-            }
-        }
-    }
-
     @Override
     public int getAvailabilityStatus(int subId) {
         if (Flags.isDualSimOnboardingEnabled()
@@ -221,20 +161,11 @@
         updateState(mPreference);
     }
 
-    private int[] getActiveSubscriptionIdList() {
-        return ProxySubscriptionManager.getInstance(mContext).getActiveSubscriptionIdList();
-    }
-
     /**
      * Trigger displaying preference when Mobile data content changed.
      */
     @VisibleForTesting
     public void refreshPreference() {
-        if (mContext.getResources().getBoolean(
-                R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
-            int[] subIds = getActiveSubscriptionIdList();
-            trySetCrossSimCalling(mContext, subIds, isEnabled(getOtherSubId(subIds)));
-        }
         if (mScreen != null) {
             super.displayPreference(mScreen);
         }
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index d57de1a..c9a2a0b 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -38,6 +38,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.lifecycle.ViewModelProvider;
 import androidx.preference.Preference;
 
 import com.android.settings.R;
@@ -53,6 +54,7 @@
 import com.android.settings.network.telephony.cdma.CdmaSystemSelectPreferenceController;
 import com.android.settings.network.telephony.gsm.AutoSelectPreferenceController;
 import com.android.settings.network.telephony.gsm.OpenNetworkSelectPagePreferenceController;
+import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.wifi.WifiPickerTrackerHelper;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -240,7 +242,9 @@
         use(CarrierSettingsVersionPreferenceController.class).init(mSubId);
         use(BillingCyclePreferenceController.class).init(mSubId);
         use(MmsMessagePreferenceController.class).init(mSubId);
-        use(AutoDataSwitchPreferenceController.class).init(mSubId);
+        final var crossSimCallingViewModel =
+                new ViewModelProvider(this).get(CrossSimCallingViewModel.class);
+        use(AutoDataSwitchPreferenceController.class).init(mSubId, crossSimCallingViewModel);
         use(DisabledSubscriptionController.class).init(mSubId);
         use(DeleteSimProfilePreferenceController.class).init(mSubId);
         use(DisableSimFooterPreferenceController.class).init(mSubId);
diff --git a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
index dd1cbd5..9bc10e5 100644
--- a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
+++ b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
@@ -51,6 +51,8 @@
         @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
         @AccessNetworkConstants.TransportType transportType: Int,
     ): Boolean
+
+    suspend fun setCrossSimCallingEnabled(enabled: Boolean)
 }
 
 class ImsMmTelRepositoryImpl(
@@ -130,6 +132,7 @@
         @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
         @AccessNetworkConstants.TransportType transportType: Int,
     ): Boolean = withContext(Dispatchers.Default) {
+        val logName = "isSupported(capability=$capability,transportType=$transportType)"
         suspendCancellableCoroutine { continuation ->
             try {
                 imsMmTelManager.isSupported(
@@ -140,9 +143,18 @@
                 )
             } catch (e: Exception) {
                 continuation.resume(false)
-                Log.w(TAG, "[$subId] isSupported failed", e)
+                Log.w(TAG, "[$subId] $logName failed", e)
             }
-        }.also { Log.d(TAG, "[$subId] isSupported = $it") }
+        }.also { Log.d(TAG, "[$subId] $logName = $it") }
+    }
+
+    override suspend fun setCrossSimCallingEnabled(enabled: Boolean) {
+        try {
+            imsMmTelManager.setCrossSimCallingEnabled(enabled)
+            Log.d(TAG, "[$subId] setCrossSimCallingEnabled: $enabled")
+        } catch (e: Exception) {
+            Log.e(TAG, "[$subId] failed setCrossSimCallingEnabled to $enabled", e)
+        }
     }
 
     private companion object {
diff --git a/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
new file mode 100644
index 0000000..5dcac1e
--- /dev/null
+++ b/src/com/android/settings/network/telephony/wificalling/CrossSimCallingViewModel.kt
@@ -0,0 +1,119 @@
+/*
+ * 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.wificalling
+
+import android.app.Application
+import android.app.settings.SettingsEnums
+import android.telephony.CarrierConfigManager
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.viewModelScope
+import com.android.settings.R
+import com.android.settings.network.mobileDataEnabledFlow
+import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
+import com.android.settings.network.telephony.requireSubscriptionManager
+import com.android.settings.network.telephony.safeGetConfig
+import com.android.settings.network.telephony.subscriptionsChangedFlow
+import com.android.settings.network.telephony.telephonyManager
+import com.android.settings.overlay.FeatureFactory.Companion.featureFactory
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.receiveAsFlow
+import kotlinx.coroutines.plus
+
+@OptIn(ExperimentalCoroutinesApi::class)
+class CrossSimCallingViewModel(
+    private val application: Application,
+) : AndroidViewModel(application) {
+
+    private val subscriptionManager = application.requireSubscriptionManager()
+    private val carrierConfigManager =
+        application.getSystemService(CarrierConfigManager::class.java)!!
+    private val scope = viewModelScope + Dispatchers.Default
+    private val metricsFeatureProvider = featureFactory.metricsFeatureProvider
+    private val updateChannel = Channel<Unit>()
+
+    init {
+        val resources = application.resources
+        if (resources.getBoolean(R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
+            application.subscriptionsChangedFlow()
+                .flatMapLatest {
+                    val activeSubIds = subscriptionManager.activeSubscriptionIdList.toList()
+                    merge(
+                        activeSubIds.anyMobileDataEnableChangedFlow(),
+                        updateChannel.receiveAsFlow(),
+                    ).map {
+                        activeSubIds to crossSimCallNewEnabled(activeSubIds)
+                    }
+                }
+                .distinctUntilChanged()
+                .onEach { (activeSubIds, newEnabled) ->
+                    updateCrossSimCalling(activeSubIds, newEnabled)
+                }
+                .launchIn(scope)
+        }
+    }
+
+    fun updateCrossSimCalling() {
+        updateChannel.trySend(Unit)
+    }
+
+    private fun List<Int>.anyMobileDataEnableChangedFlow() = map { subId ->
+        application.mobileDataEnabledFlow(subId = subId, sendInitialValue = false)
+    }.merge()
+
+    private suspend fun updateCrossSimCalling(activeSubIds: List<Int>, newEnabled: Boolean) {
+        metricsFeatureProvider.action(
+            application,
+            SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT,
+            newEnabled,
+        )
+        activeSubIds.filter { crossSimAvailable(it) }.forEach { subId ->
+            ImsMmTelRepositoryImpl(application, subId)
+                .setCrossSimCallingEnabled(newEnabled)
+        }
+    }
+
+    private suspend fun crossSimAvailable(subId: Int): Boolean =
+        WifiCallingRepository(application, subId).isWifiCallingSupported() &&
+            crossSimImsAvailable(subId)
+
+    private fun crossSimImsAvailable(subId: Int): Boolean =
+        carrierConfigManager.safeGetConfig(
+            keys = listOf(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL),
+            subId = subId,
+        ).getBoolean(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false)
+
+    private fun crossSimCallNewEnabled(activeSubscriptionIdList: List<Int>): Boolean {
+        val defaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId()
+        return SubscriptionManager.isValidSubscriptionId(defaultDataSubId) &&
+            activeSubscriptionIdList.any { subId ->
+                subId != defaultDataSubId &&
+                    application.telephonyManager(subId).isMobileDataPolicyEnabled(
+                        TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH
+                    )
+            }
+    }
+}
diff --git a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
index ac95404..a5d4ba8 100644
--- a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
+++ b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
@@ -29,17 +29,19 @@
 import com.android.settings.network.telephony.ims.ImsMmTelRepositoryImpl
 import com.android.settings.network.telephony.ims.imsFeatureProvisionedFlow
 import com.android.settings.network.telephony.subscriptionsChangedFlow
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.flatMapLatest
 import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.withContext
 
 class WifiCallingRepository(
     private val context: Context,
     private val subId: Int,
-    private val imsMmTelRepository : ImsMmTelRepository = ImsMmTelRepositoryImpl(context, subId)
+    private val imsMmTelRepository: ImsMmTelRepository = ImsMmTelRepositoryImpl(context, subId)
 ) {
     private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
         .createForSubscriptionId(subId)
@@ -76,10 +78,14 @@
 
     private fun isWifiCallingSupportedFlow(): Flow<Boolean> {
         return imsMmTelRepository.imsReadyFlow().map { imsReady ->
-            imsReady && imsMmTelRepository.isSupported(
-                capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
-                transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
-            )
+            imsReady && isWifiCallingSupported()
         }
     }
+
+    suspend fun isWifiCallingSupported(): Boolean = withContext(Dispatchers.Default) {
+        imsMmTelRepository.isSupported(
+            capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+            transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
+        )
+    }
 }
diff --git a/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt b/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
index 824a935..e79be4a 100644
--- a/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
+++ b/src/com/android/settings/spa/network/AutomaticDataSwitchingPreference.kt
@@ -20,8 +20,10 @@
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.rememberCoroutineScope
 import androidx.compose.ui.res.stringResource
+import androidx.lifecycle.viewmodel.compose.viewModel
 import com.android.settings.R
 import com.android.settings.network.telephony.TelephonyRepository
+import com.android.settings.network.telephony.wificalling.CrossSimCallingViewModel
 import com.android.settingslib.spa.widget.preference.SwitchPreference
 import com.android.settingslib.spa.widget.preference.SwitchPreferenceModel
 import kotlinx.coroutines.Dispatchers
@@ -34,6 +36,7 @@
 ) {
     val autoDataSummary = stringResource(id = R.string.primary_sim_automatic_data_msg)
     val coroutineScope = rememberCoroutineScope()
+    val crossSimCallingViewModel = viewModel<CrossSimCallingViewModel>() // handles backup calling
     SwitchPreference(
         object : SwitchPreferenceModel {
             override val title = stringResource(id = R.string.primary_sim_automatic_data_title)
@@ -42,6 +45,7 @@
             override val onCheckedChange: (Boolean) -> Unit = { newEnabled ->
                 coroutineScope.launch(Dispatchers.Default) {
                     setAutoDataEnabled(newEnabled)
+                    crossSimCallingViewModel.updateCrossSimCalling()
                 }
             }
         }
@@ -54,5 +58,4 @@
         policy = TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
         enabled = newEnabled,
     )
-    //TODO: setup backup calling
 }
diff --git a/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
index 29592cf..8db4681 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceControllerTest.java
@@ -85,7 +85,7 @@
                 return true;
             }
         };
-        mController.init(SUB_ID_1);
+        mController.init(SUB_ID_1, null);
     }
 
     @Test
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt
index f198660..04cba73 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsMmTelRepositoryTest.kt
@@ -43,6 +43,7 @@
 import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.stub
+import org.mockito.kotlin.verify
 
 @RunWith(AndroidJUnit4::class)
 class ImsMmTelRepositoryTest {
@@ -155,6 +156,13 @@
         assertThat(isSupported).isTrue()
     }
 
+    @Test
+    fun setCrossSimCallingEnabled() = runBlocking {
+        repository.setCrossSimCallingEnabled(true)
+
+        verify(mockImsMmTelManager).setCrossSimCallingEnabled(true)
+    }
+
     private companion object {
         const val SUB_ID = 1
         const val CAPABILITY = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
index 1f3acc2..0144f66 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/wificalling/WifiCallingRepositoryTest.kt
@@ -17,15 +17,18 @@
 package com.android.settings.network.telephony.wificalling
 
 import android.content.Context
+import android.telephony.AccessNetworkConstants
 import android.telephony.CarrierConfigManager
 import android.telephony.CarrierConfigManager.KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL
 import android.telephony.TelephonyManager
 import android.telephony.ims.ImsMmTelManager
+import android.telephony.ims.feature.MmTelFeature
 import androidx.core.os.persistableBundleOf
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import com.android.settings.network.telephony.ims.ImsMmTelRepository
 import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.kotlin.any
@@ -98,6 +101,22 @@
         assertThat(wiFiCallingMode).isEqualTo(ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED)
     }
 
+    @Test
+    fun isWifiCallingSupported() = runBlocking {
+        mockImsMmTelRepository.stub {
+            onBlocking {
+                isSupported(
+                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+                    transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
+                )
+            } doReturn true
+        }
+
+        val isSupported = repository.isWifiCallingSupported()
+
+        assertThat(isSupported).isTrue()
+    }
+
     private fun mockUseWfcHomeModeForRoaming(config: Boolean) {
         mockCarrierConfigManager.stub {
             on {