Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f245b3e0 authored by Chaohui Wang's avatar Chaohui Wang
Browse files

Create ProvisioningRepository

Also check if has IMS feature before calling ProvisioningManager.

Bug: 358000881
Flag: EXEMPT refactor
Test: manual - on Mobile Settings
Test: atest ProvisioningRepositoryTest
Change-Id: I5fffff6c63af8c67d666b0e855f026633bb36651
parent a6678ad6
Loading
Loading
Loading
Loading
+99 −0
Original line number Diff line number Diff line
@@ -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
@@ -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(
@@ -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"
    }
}
+3 −2
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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,
+40 −9
Original line number Diff line number Diff line
@@ -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
@@ -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()

@@ -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)

@@ -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
    }