Merge "Fix Wi-Fi calling option does not appear" into main
diff --git a/src/com/android/settings/network/ims/WifiCallingQueryImsState.java b/src/com/android/settings/network/ims/WifiCallingQueryImsState.java
index efa93e5..00d162b 100644
--- a/src/com/android/settings/network/ims/WifiCallingQueryImsState.java
+++ b/src/com/android/settings/network/ims/WifiCallingQueryImsState.java
@@ -27,6 +27,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.settings.network.telephony.wificalling.WifiCallingRepository;
+
 /**
  * Controller class for querying Wifi calling status
  */
@@ -92,7 +94,9 @@
      * Check whether Wifi Calling can be perform or not on this subscription
      *
      * @return true when Wifi Calling can be performed, otherwise false
+     * @deprecated Use {@link WifiCallingRepository#wifiCallingReadyFlow()} instead.
      */
+    @Deprecated
     public boolean isReadyToWifiCalling() {
         if (!SubscriptionManager.isValidSubscriptionId(mSubId)) {
             return false;
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index 47515d8..8a63505 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -80,6 +80,7 @@
 import com.android.settings.network.SubscriptionUtil;
 import com.android.settings.network.ims.WifiCallingQueryImsState;
 import com.android.settings.network.telephony.TelephonyConstants.TelephonyManagerConstants;
+import com.android.settings.network.telephony.wificalling.WifiCallingRepository;
 import com.android.settingslib.core.instrumentation.Instrumentable;
 import com.android.settingslib.development.DevelopmentSettingsEnabler;
 import com.android.settingslib.graph.SignalDrawable;
@@ -928,7 +929,10 @@
 
     /**
      * Copied from WifiCallingPreferenceController#isWifiCallingEnabled()
+     *
+     * @deprecated Use {@link WifiCallingRepository#wifiCallingReadyFlow()} instead.
      */
+    @Deprecated
     public static boolean isWifiCallingEnabled(Context context, int subId,
             @Nullable WifiCallingQueryImsState queryImsState) {
         if (queryImsState == null) {
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index 7a14d6b..ee4ac1e 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -18,12 +18,16 @@
 
 import android.content.Context
 import android.telephony.SubscriptionManager
+import android.util.Log
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.asExecutor
 import kotlinx.coroutines.channels.awaitClose
 import kotlinx.coroutines.flow.callbackFlow
 import kotlinx.coroutines.flow.conflate
 import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.onEach
+
+private const val TAG = "SubscriptionRepository"
 
 fun Context.subscriptionsChangedFlow() = callbackFlow {
     val subscriptionManager = getSystemService(SubscriptionManager::class.java)!!
@@ -40,4 +44,4 @@
     )
 
     awaitClose { subscriptionManager.removeOnSubscriptionsChangedListener(listener) }
-}.conflate().flowOn(Dispatchers.Default)
+}.conflate().onEach { Log.d(TAG, "subscriptions changed") }.flowOn(Dispatchers.Default)
diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
index 698341c..b0ea6a6 100644
--- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
+++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.kt
@@ -45,7 +45,7 @@
     context: Context,
     key: String,
     private val callStateFlowFactory: (subId: Int) -> Flow<Int> = context::callStateFlow,
-    private val wifiCallingRepository: (subId: Int) -> WifiCallingRepository = { subId ->
+    private val wifiCallingRepositoryFactory: (subId: Int) -> WifiCallingRepository = { subId ->
         WifiCallingRepository(context, subId)
     },
 ) : TelephonyBasePreferenceController(context, key) {
@@ -80,15 +80,11 @@
     }
 
     override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
-        viewLifecycleOwner.lifecycleScope.launch {
-            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
-                val isVisible = withContext(Dispatchers.Default) {
-                    MobileNetworkUtils.isWifiCallingEnabled(mContext, mSubId, null)
-                }
-                preference.isVisible = isVisible
-                callingPreferenceCategoryController.updateChildVisible(preferenceKey, isVisible)
+        wifiCallingRepositoryFactory(mSubId).wifiCallingReadyFlow()
+            .collectLatestWithLifecycle(viewLifecycleOwner) {
+                preference.isVisible = it
+                callingPreferenceCategoryController.updateChildVisible(preferenceKey, it)
             }
-        }
 
         viewLifecycleOwner.lifecycleScope.launch {
             viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
@@ -122,7 +118,7 @@
     }
 
     private fun getSummaryForWfcMode(): String {
-        val resId = when (wifiCallingRepository(mSubId).getWiFiCallingMode()) {
+        val resId = when (wifiCallingRepositoryFactory(mSubId).getWiFiCallingMode()) {
             ImsMmTelManager.WIFI_MODE_WIFI_ONLY ->
                 com.android.internal.R.string.wfc_mode_wifi_only_summary
 
diff --git a/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlow.kt b/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlow.kt
new file mode 100644
index 0000000..6769498
--- /dev/null
+++ b/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlow.kt
@@ -0,0 +1,83 @@
+/*
+ * 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.ims
+
+import android.telephony.ims.ProvisioningManager
+import android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback
+import android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.MmTelCapability
+import android.telephony.ims.stub.ImsRegistrationImplBase.ImsRegistrationTech
+import android.util.Log
+import androidx.annotation.VisibleForTesting
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.onEach
+
+private const val TAG = "ImsFeatureProvisioned"
+
+fun imsFeatureProvisionedFlow(
+    subId: Int,
+    @MmTelCapability capability: Int,
+    @ImsRegistrationTech tech: Int,
+): Flow<Boolean> = imsFeatureProvisionedFlow(
+    subId = subId,
+    capability = capability,
+    tech = tech,
+    provisioningManager = ProvisioningManager.createForSubscriptionId(subId),
+)
+
+@VisibleForTesting
+fun imsFeatureProvisionedFlow(
+    subId: Int,
+    @MmTelCapability capability: Int,
+    @ImsRegistrationTech tech: Int,
+    provisioningManager : ProvisioningManager,
+): Flow<Boolean> = callbackFlow {
+    val callback = object : FeatureProvisioningCallback() {
+        override fun onFeatureProvisioningChanged(
+            receivedCapability: Int,
+            receivedTech: Int,
+            isProvisioned: Boolean,
+        ) {
+            if (capability == receivedCapability && tech == receivedTech) trySend(isProvisioned)
+        }
+
+        override fun onRcsFeatureProvisioningChanged(
+            capability: Int,
+            tech: Int,
+            isProvisioned: Boolean,
+        ) {
+        }
+    }
+
+    provisioningManager.registerFeatureProvisioningChangedCallback(
+        Dispatchers.Default.asExecutor(),
+        callback,
+    )
+    trySend(provisioningManager.getProvisioningStatusForCapability(capability, tech))
+
+    awaitClose { provisioningManager.unregisterFeatureProvisioningChangedCallback(callback) }
+}.catch { e ->
+    Log.w(TAG, "[$subId] error while imsFeatureProvisionedFlow", e)
+}.conflate().onEach {
+    Log.d(TAG, "[$subId] changed: capability=$capability tech=$tech isProvisioned=$it")
+}.flowOn(Dispatchers.Default)
diff --git a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
index 1d288d4..822c20a 100644
--- a/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
+++ b/src/com/android/settings/network/telephony/ims/ImsMmTelRepository.kt
@@ -17,14 +17,33 @@
 package com.android.settings.network.telephony.ims
 
 import android.content.Context
+import android.telephony.AccessNetworkConstants
 import android.telephony.ims.ImsManager
 import android.telephony.ims.ImsMmTelManager
 import android.telephony.ims.ImsMmTelManager.WiFiCallingMode
+import android.telephony.ims.ImsStateCallback
+import android.telephony.ims.feature.MmTelFeature
 import android.util.Log
+import kotlin.coroutines.resume
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.asExecutor
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.callbackFlow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.conflate
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.suspendCancellableCoroutine
+import kotlinx.coroutines.withContext
 
 interface ImsMmTelRepository {
     @WiFiCallingMode
     fun getWiFiCallingMode(useRoamingMode: Boolean): Int
+    fun imsReadyFlow(): Flow<Boolean>
+    suspend fun isSupported(
+        @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
+        @AccessNetworkConstants.TransportType transportType: Int,
+    ): Boolean
 }
 
 class ImsMmTelRepositoryImpl(
@@ -45,6 +64,50 @@
         ImsMmTelManager.WIFI_MODE_UNKNOWN
     }
 
+    override fun imsReadyFlow(): Flow<Boolean> = callbackFlow {
+        val callback = object : ImsStateCallback() {
+            override fun onAvailable() {
+                Log.d(TAG, "[$subId] IMS onAvailable")
+                trySend(true)
+            }
+
+            override fun onError() {
+                Log.d(TAG, "[$subId] IMS onError")
+                trySend(false)
+            }
+
+            override fun onUnavailable(reason: Int) {
+                Log.d(TAG, "[$subId] IMS onUnavailable")
+                trySend(false)
+            }
+        }
+
+        imsMmTelManager.registerImsStateCallback(Dispatchers.Default.asExecutor(), callback)
+
+        awaitClose { imsMmTelManager.unregisterImsStateCallback(callback) }
+    }.catch { e ->
+        Log.w(TAG, "[$subId] error while imsReadyFlow", e)
+    }.conflate().flowOn(Dispatchers.Default)
+
+    override suspend fun isSupported(
+        @MmTelFeature.MmTelCapabilities.MmTelCapability capability: Int,
+        @AccessNetworkConstants.TransportType transportType: Int,
+    ): Boolean = withContext(Dispatchers.Default) {
+        suspendCancellableCoroutine { continuation ->
+            try {
+                imsMmTelManager.isSupported(
+                    capability,
+                    transportType,
+                    Dispatchers.Default.asExecutor(),
+                    continuation::resume,
+                )
+            } catch (e: Exception) {
+                continuation.resume(false)
+                Log.w(TAG, "[$subId] isSupported failed", e)
+            }
+        }.also { Log.d(TAG, "[$subId] isSupported = $it") }
+    }
+
     private companion object {
         private const val TAG = "ImsMmTelRepository"
     }
diff --git a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
index 3d841d5..ac95404 100644
--- a/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
+++ b/src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt
@@ -17,12 +17,24 @@
 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.SubscriptionManager
 import android.telephony.TelephonyManager
 import android.telephony.ims.ImsMmTelManager.WiFiCallingMode
+import android.telephony.ims.feature.MmTelFeature
+import android.telephony.ims.stub.ImsRegistrationImplBase
 import com.android.settings.network.telephony.ims.ImsMmTelRepository
 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.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
 
 class WifiCallingRepository(
     private val context: Context,
@@ -44,4 +56,30 @@
         carrierConfigManager
             .getConfigForSubId(subId, KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL)
             .getBoolean(KEY_USE_WFC_HOME_NETWORK_MODE_IN_ROAMING_NETWORK_BOOL)
+
+    @OptIn(ExperimentalCoroutinesApi::class)
+    fun wifiCallingReadyFlow(): Flow<Boolean> {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
+        return context.subscriptionsChangedFlow().flatMapLatest {
+            combine(
+                imsFeatureProvisionedFlow(
+                    subId = subId,
+                    capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+                    tech = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
+                ),
+                isWifiCallingSupportedFlow(),
+            ) { imsFeatureProvisioned, isWifiCallingSupported ->
+                imsFeatureProvisioned && isWifiCallingSupported
+            }
+        }
+    }
+
+    private fun isWifiCallingSupportedFlow(): Flow<Boolean> {
+        return imsMmTelRepository.imsReadyFlow().map { imsReady ->
+            imsReady && imsMmTelRepository.isSupported(
+                capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE,
+                transportType = AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
+            )
+        }
+    }
 }
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.kt
index f947f81..92776df 100644
--- a/tests/spa_unit/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.kt
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.kt
@@ -62,6 +62,7 @@
 
     private val mockWifiCallingRepository = mock<WifiCallingRepository> {
         on { getWiFiCallingMode() } doReturn ImsMmTelManager.WIFI_MODE_UNKNOWN
+        on { wifiCallingReadyFlow() } doReturn flowOf(true)
     }
 
     private val callingPreferenceCategoryController =
@@ -71,7 +72,7 @@
         context = context,
         key = TEST_KEY,
         callStateFlowFactory = { flowOf(callState) },
-        wifiCallingRepository = { mockWifiCallingRepository },
+        wifiCallingRepositoryFactory = { mockWifiCallingRepository },
     ).init(subId = SUB_ID, callingPreferenceCategoryController)
 
     @Before
diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlowTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlowTest.kt
new file mode 100644
index 0000000..75f933a
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlowTest.kt
@@ -0,0 +1,75 @@
+/*
+ * 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.ims
+
+import android.telephony.ims.ProvisioningManager
+import android.telephony.ims.ProvisioningManager.FeatureProvisioningCallback
+import android.telephony.ims.feature.MmTelFeature
+import android.telephony.ims.stub.ImsRegistrationImplBase
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.toListWithTimeout
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
+import org.mockito.kotlin.mock
+
+@RunWith(AndroidJUnit4::class)
+class ImsFeatureProvisionedFlowTest {
+
+    private var callback: FeatureProvisioningCallback? = null
+
+    private val mockProvisioningManager = mock<ProvisioningManager> {
+        on { registerFeatureProvisioningChangedCallback(any(), any()) } doAnswer {
+            callback = it.arguments[1] as FeatureProvisioningCallback
+            callback?.onFeatureProvisioningChanged(CAPABILITY, TECH, true)
+        }
+    }
+
+    @Test
+    fun imsFeatureProvisionedFlow_sendInitialValue() = runBlocking {
+        val flow = imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH, mockProvisioningManager)
+
+        val state = flow.first()
+
+        assertThat(state).isTrue()
+    }
+
+    @Test
+    fun imsFeatureProvisionedFlow_changed(): Unit = runBlocking {
+        val listDeferred = async {
+            imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH, mockProvisioningManager)
+                .toListWithTimeout()
+        }
+        delay(100)
+
+        callback?.onFeatureProvisioningChanged(CAPABILITY, TECH, false)
+
+        assertThat(listDeferred.await().last()).isFalse()
+    }
+
+    private companion object {
+        const val SUB_ID = 1
+        const val CAPABILITY = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE
+        const val TECH = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN
+    }
+}
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 106a82f..24b081a 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
@@ -17,14 +17,26 @@
 package com.android.settings.network.telephony.ims
 
 import android.content.Context
+import android.telephony.AccessNetworkConstants
 import android.telephony.ims.ImsMmTelManager
+import android.telephony.ims.ImsStateCallback
+import android.telephony.ims.feature.MmTelFeature
 import androidx.test.core.app.ApplicationProvider
 import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spa.testutils.toListWithTimeout
 import com.google.common.truth.Truth.assertThat
+import java.util.function.Consumer
+import kotlinx.coroutines.async
+import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.runBlocking
 import org.junit.Test
 import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doAnswer
 import org.mockito.kotlin.doReturn
 import org.mockito.kotlin.doThrow
+import org.mockito.kotlin.eq
 import org.mockito.kotlin.mock
 import org.mockito.kotlin.stub
 
@@ -32,10 +44,21 @@
 class ImsMmTelRepositoryTest {
     private val context: Context = ApplicationProvider.getApplicationContext()
 
+    private var stateCallback: ImsStateCallback? = null
+
     private val mockImsMmTelManager = mock<ImsMmTelManager> {
         on { isVoWiFiSettingEnabled } doReturn true
         on { getVoWiFiRoamingModeSetting() } doReturn ImsMmTelManager.WIFI_MODE_WIFI_PREFERRED
         on { getVoWiFiModeSetting() } doReturn ImsMmTelManager.WIFI_MODE_CELLULAR_PREFERRED
+        on { registerImsStateCallback(any(), any()) } doAnswer {
+            stateCallback = it.arguments[1] as ImsStateCallback
+            stateCallback?.onAvailable()
+        }
+        on { isSupported(eq(CAPABILITY), eq(TRANSPORT), any(), any()) } doAnswer {
+            @Suppress("UNCHECKED_CAST")
+            val consumer = it.arguments[3] as Consumer<Boolean>
+            consumer.accept(true)
+        }
     }
 
     private val repository = ImsMmTelRepositoryImpl(context, SUB_ID, mockImsMmTelManager)
@@ -76,7 +99,37 @@
         assertThat(wiFiCallingMode).isEqualTo(ImsMmTelManager.WIFI_MODE_UNKNOWN)
     }
 
+    @Test
+    fun imsReadyFlow_sendInitialValue() = runBlocking {
+        val flow = repository.imsReadyFlow()
+
+        val state = flow.first()
+
+        assertThat(state).isTrue()
+    }
+
+    @Test
+    fun imsReadyFlow_changed(): Unit = runBlocking {
+        val listDeferred = async {
+            repository.imsReadyFlow().toListWithTimeout()
+        }
+        delay(100)
+
+        stateCallback?.onUnavailable(ImsStateCallback.REASON_IMS_SERVICE_NOT_READY)
+
+        assertThat(listDeferred.await().last()).isFalse()
+    }
+
+    @Test
+    fun isSupported() = runBlocking {
+        val isSupported = repository.isSupported(CAPABILITY, TRANSPORT)
+
+        assertThat(isSupported).isTrue()
+    }
+
     private companion object {
         const val SUB_ID = 1
+        const val CAPABILITY = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE
+        const val TRANSPORT = AccessNetworkConstants.TRANSPORT_TYPE_WLAN
     }
 }