Loading src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlow.kt→src/com/android/settings/network/telephony/ims/ProvisioningRepository.kt +99 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.settings.network.telephony.ims import android.content.Context import android.content.pm.PackageManager import android.telephony.SubscriptionManager 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 Loading @@ -29,44 +31,44 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf 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), ) class ProvisioningRepository( private val context: Context, private val provisioningManagerFactory: (Int) -> ProvisioningManager = ProvisioningManager::createForSubscriptionId, ) { @VisibleForTesting fun imsFeatureProvisionedFlow( subId: Int, @MmTelCapability capability: Int, @ImsRegistrationTech tech: Int, provisioningManager : ProvisioningManager, ): Flow<Boolean> = callbackFlow { val callback = object : FeatureProvisioningCallback() { ): Flow<Boolean> { if (!SubscriptionManager.isValidSubscriptionId(subId) || !context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) { return flowOf(false) } val provisioningManager = provisioningManagerFactory(subId) return callbackFlow { val callback = object : FeatureProvisioningCallback() { override fun onFeatureProvisioningChanged( receivedCapability: Int, receivedTech: Int, isProvisioned: Boolean, ) { if (capability == receivedCapability && tech == receivedTech) trySend(isProvisioned) if (capability == receivedCapability && tech == receivedTech) trySend(isProvisioned) } override fun onRcsFeatureProvisioningChanged( capability: Int, tech: Int, isProvisioned: Boolean, ) { } ) {} } provisioningManager.registerFeatureProvisioningChangedCallback( Loading @@ -75,9 +77,23 @@ fun imsFeatureProvisionedFlow( ) trySend(provisioningManager.getProvisioningStatusForCapability(capability, tech)) awaitClose { provisioningManager.unregisterFeatureProvisioningChangedCallback(callback) } }.catch { e -> awaitClose { provisioningManager.unregisterFeatureProvisioningChangedCallback(callback) } } .catch { e -> Log.w(TAG, "[$subId] error while imsFeatureProvisionedFlow", e) }.conflate().onEach { emit(false) } .distinctUntilChanged() .conflate() .onEach { Log.d(TAG, "[$subId] changed: capability=$capability tech=$tech isProvisioned=$it") }.flowOn(Dispatchers.Default) } .flowOn(Dispatchers.Default) } companion object { private const val TAG = "ProvisioningRepository" } } src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import android.telephony.ims.stub.ImsRegistrationImplBase import androidx.lifecycle.LifecycleOwner 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.ims.ProvisioningRepository import com.android.settings.network.telephony.subscriptionsChangedFlow import com.android.settings.network.telephony.telephonyManager import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle Loading @@ -54,6 +54,7 @@ constructor( ) : IWifiCallingRepository { private val telephonyManager = context.telephonyManager(subId) private val provisioningRepository = ProvisioningRepository(context) private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)!! @WiFiCallingMode Loading @@ -80,7 +81,7 @@ constructor( if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false) return context.subscriptionsChangedFlow().flatMapLatest { combine( imsFeatureProvisionedFlow( provisioningRepository.imsFeatureProvisionedFlow( subId = subId, capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, tech = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, Loading tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlowTest.kt→tests/spa_unit/src/com/android/settings/network/telephony/ims/ProvisioningRepositoryTest.kt +40 −9 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.settings.network.telephony.ims import android.content.Context import android.content.pm.PackageManager 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.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settingslib.spa.testutils.toListWithTimeout import com.google.common.truth.Truth.assertThat Loading @@ -31,23 +34,52 @@ 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.mock import org.mockito.kotlin.spy import org.mockito.kotlin.stub @RunWith(AndroidJUnit4::class) class ImsFeatureProvisionedFlowTest { class ProvisioningRepositoryTest { private var callback: FeatureProvisioningCallback? = null private val mockProvisioningManager = mock<ProvisioningManager> { on { registerFeatureProvisioningChangedCallback(any(), any()) } doAnswer { private val mockProvisioningManager = mock<ProvisioningManager> { on { registerFeatureProvisioningChangedCallback(any(), any()) } doAnswer { callback = it.arguments[1] as FeatureProvisioningCallback callback?.onFeatureProvisioningChanged(CAPABILITY, TECH, true) } } private val mockPackageManager = mock<PackageManager> { on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS) } doReturn true } private val context: Context = spy(ApplicationProvider.getApplicationContext()) { on { packageManager } doReturn mockPackageManager } private val repository = ProvisioningRepository(context) { mockProvisioningManager } @Test fun imsFeatureProvisionedFlow_hasNotIms_returnFalse() = runBlocking { mockPackageManager.stub { on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS) } doReturn false } val flow = repository.imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH) val state = flow.first() assertThat(state).isFalse() } @Test fun imsFeatureProvisionedFlow_sendInitialValue() = runBlocking { val flow = imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH, mockProvisioningManager) val flow = repository.imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH) val state = flow.first() Loading @@ -57,8 +89,7 @@ class ImsFeatureProvisionedFlowTest { @Test fun imsFeatureProvisionedFlow_changed(): Unit = runBlocking { val listDeferred = async { imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH, mockProvisioningManager) .toListWithTimeout() repository.imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH).toListWithTimeout() } delay(100) Loading @@ -68,7 +99,7 @@ class ImsFeatureProvisionedFlowTest { } private companion object { const val SUB_ID = 1 const val SUB_ID = 10 const val CAPABILITY = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE const val TECH = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN } Loading Loading
src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlow.kt→src/com/android/settings/network/telephony/ims/ProvisioningRepository.kt +99 −0 Original line number Diff line number Diff line Loading @@ -16,12 +16,14 @@ package com.android.settings.network.telephony.ims import android.content.Context import android.content.pm.PackageManager import android.telephony.SubscriptionManager 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 Loading @@ -29,44 +31,44 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.catch import kotlinx.coroutines.flow.conflate import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flowOf 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), ) class ProvisioningRepository( private val context: Context, private val provisioningManagerFactory: (Int) -> ProvisioningManager = ProvisioningManager::createForSubscriptionId, ) { @VisibleForTesting fun imsFeatureProvisionedFlow( subId: Int, @MmTelCapability capability: Int, @ImsRegistrationTech tech: Int, provisioningManager : ProvisioningManager, ): Flow<Boolean> = callbackFlow { val callback = object : FeatureProvisioningCallback() { ): Flow<Boolean> { if (!SubscriptionManager.isValidSubscriptionId(subId) || !context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) { return flowOf(false) } val provisioningManager = provisioningManagerFactory(subId) return callbackFlow { val callback = object : FeatureProvisioningCallback() { override fun onFeatureProvisioningChanged( receivedCapability: Int, receivedTech: Int, isProvisioned: Boolean, ) { if (capability == receivedCapability && tech == receivedTech) trySend(isProvisioned) if (capability == receivedCapability && tech == receivedTech) trySend(isProvisioned) } override fun onRcsFeatureProvisioningChanged( capability: Int, tech: Int, isProvisioned: Boolean, ) { } ) {} } provisioningManager.registerFeatureProvisioningChangedCallback( Loading @@ -75,9 +77,23 @@ fun imsFeatureProvisionedFlow( ) trySend(provisioningManager.getProvisioningStatusForCapability(capability, tech)) awaitClose { provisioningManager.unregisterFeatureProvisioningChangedCallback(callback) } }.catch { e -> awaitClose { provisioningManager.unregisterFeatureProvisioningChangedCallback(callback) } } .catch { e -> Log.w(TAG, "[$subId] error while imsFeatureProvisionedFlow", e) }.conflate().onEach { emit(false) } .distinctUntilChanged() .conflate() .onEach { Log.d(TAG, "[$subId] changed: capability=$capability tech=$tech isProvisioned=$it") }.flowOn(Dispatchers.Default) } .flowOn(Dispatchers.Default) } companion object { private const val TAG = "ProvisioningRepository" } }
src/com/android/settings/network/telephony/wificalling/WifiCallingRepository.kt +3 −2 Original line number Diff line number Diff line Loading @@ -27,7 +27,7 @@ import android.telephony.ims.stub.ImsRegistrationImplBase import androidx.lifecycle.LifecycleOwner 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.ims.ProvisioningRepository import com.android.settings.network.telephony.subscriptionsChangedFlow import com.android.settings.network.telephony.telephonyManager import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle Loading @@ -54,6 +54,7 @@ constructor( ) : IWifiCallingRepository { private val telephonyManager = context.telephonyManager(subId) private val provisioningRepository = ProvisioningRepository(context) private val carrierConfigManager = context.getSystemService(CarrierConfigManager::class.java)!! @WiFiCallingMode Loading @@ -80,7 +81,7 @@ constructor( if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false) return context.subscriptionsChangedFlow().flatMapLatest { combine( imsFeatureProvisionedFlow( provisioningRepository.imsFeatureProvisionedFlow( subId = subId, capability = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE, tech = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, Loading
tests/spa_unit/src/com/android/settings/network/telephony/ims/ImsFeatureProvisionedFlowTest.kt→tests/spa_unit/src/com/android/settings/network/telephony/ims/ProvisioningRepositoryTest.kt +40 −9 Original line number Diff line number Diff line Loading @@ -16,10 +16,13 @@ package com.android.settings.network.telephony.ims import android.content.Context import android.content.pm.PackageManager 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.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settingslib.spa.testutils.toListWithTimeout import com.google.common.truth.Truth.assertThat Loading @@ -31,23 +34,52 @@ 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.mock import org.mockito.kotlin.spy import org.mockito.kotlin.stub @RunWith(AndroidJUnit4::class) class ImsFeatureProvisionedFlowTest { class ProvisioningRepositoryTest { private var callback: FeatureProvisioningCallback? = null private val mockProvisioningManager = mock<ProvisioningManager> { on { registerFeatureProvisioningChangedCallback(any(), any()) } doAnswer { private val mockProvisioningManager = mock<ProvisioningManager> { on { registerFeatureProvisioningChangedCallback(any(), any()) } doAnswer { callback = it.arguments[1] as FeatureProvisioningCallback callback?.onFeatureProvisioningChanged(CAPABILITY, TECH, true) } } private val mockPackageManager = mock<PackageManager> { on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS) } doReturn true } private val context: Context = spy(ApplicationProvider.getApplicationContext()) { on { packageManager } doReturn mockPackageManager } private val repository = ProvisioningRepository(context) { mockProvisioningManager } @Test fun imsFeatureProvisionedFlow_hasNotIms_returnFalse() = runBlocking { mockPackageManager.stub { on { hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS) } doReturn false } val flow = repository.imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH) val state = flow.first() assertThat(state).isFalse() } @Test fun imsFeatureProvisionedFlow_sendInitialValue() = runBlocking { val flow = imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH, mockProvisioningManager) val flow = repository.imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH) val state = flow.first() Loading @@ -57,8 +89,7 @@ class ImsFeatureProvisionedFlowTest { @Test fun imsFeatureProvisionedFlow_changed(): Unit = runBlocking { val listDeferred = async { imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH, mockProvisioningManager) .toListWithTimeout() repository.imsFeatureProvisionedFlow(SUB_ID, CAPABILITY, TECH).toListWithTimeout() } delay(100) Loading @@ -68,7 +99,7 @@ class ImsFeatureProvisionedFlowTest { } private companion object { const val SUB_ID = 1 const val SUB_ID = 10 const val CAPABILITY = MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE const val TECH = ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN } Loading