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

Commit 544cf324 authored by Chaohui Wang's avatar Chaohui Wang Committed by Android (Google) Code Review
Browse files

Merge "Create ProvisioningRepository" into main

parents d19cd221 f245b3e0
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
    }