Merge "Catch exception in telephonyRepository.isDataEnabledFlow" into main
This commit is contained in:
@@ -26,11 +26,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.core.SubSettingLauncher
|
import com.android.settings.core.SubSettingLauncher
|
||||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||||
import com.android.settings.network.mobileDataEnabledFlow
|
|
||||||
import com.android.settings.spa.preference.ComposePreference
|
import com.android.settings.spa.preference.ComposePreference
|
||||||
import com.android.settingslib.spa.widget.preference.Preference
|
import com.android.settingslib.spa.widget.preference.Preference
|
||||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||||
import kotlinx.coroutines.flow.map
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference which displays billing cycle of subscription
|
* Preference which displays billing cycle of subscription
|
||||||
@@ -46,8 +44,8 @@ class BillingCyclePreference @JvmOverloads constructor(
|
|||||||
|
|
||||||
override fun setTemplate(template: NetworkTemplate, subId: Int) {
|
override fun setTemplate(template: NetworkTemplate, subId: Int) {
|
||||||
setContent {
|
setContent {
|
||||||
val isModifiable by remember {
|
val isModifiable by remember(subId) {
|
||||||
context.mobileDataEnabledFlow(subId).map { repository.isModifiable(subId) }
|
repository.isModifiableFlow(subId)
|
||||||
}.collectAsStateWithLifecycle(initialValue = false)
|
}.collectAsStateWithLifecycle(initialValue = false)
|
||||||
|
|
||||||
Preference(object : PreferenceModel {
|
Preference(object : PreferenceModel {
|
||||||
|
@@ -35,7 +35,7 @@ import com.android.settings.datausage.lib.BillingCycleRepository
|
|||||||
import com.android.settings.datausage.lib.NetworkUsageData
|
import com.android.settings.datausage.lib.NetworkUsageData
|
||||||
import com.android.settings.network.MobileNetworkRepository
|
import com.android.settings.network.MobileNetworkRepository
|
||||||
import com.android.settings.network.SubscriptionUtil
|
import com.android.settings.network.SubscriptionUtil
|
||||||
import com.android.settings.network.mobileDataEnabledFlow
|
import com.android.settings.network.telephony.requireSubscriptionManager
|
||||||
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity
|
import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity
|
||||||
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
|
||||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||||
@@ -113,8 +113,8 @@ open class DataUsageList : DashboardFragment() {
|
|||||||
override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(v, savedInstanceState)
|
super.onViewCreated(v, savedInstanceState)
|
||||||
|
|
||||||
requireContext().mobileDataEnabledFlow(subId)
|
billingCycleRepository.isModifiableFlow(subId)
|
||||||
.collectLatestWithLifecycle(viewLifecycleOwner) { updatePolicy() }
|
.collectLatestWithLifecycle(viewLifecycleOwner, action = ::updatePolicy)
|
||||||
|
|
||||||
val template = template ?: return
|
val template = template ?: return
|
||||||
viewModel.templateFlow.value = template
|
viewModel.templateFlow.value = template
|
||||||
@@ -163,16 +163,14 @@ open class DataUsageList : DashboardFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
|
/** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
|
||||||
private fun updatePolicy() {
|
private fun updatePolicy(isModifiable: Boolean) {
|
||||||
val isBillingCycleModifiable = isBillingCycleModifiable()
|
val isBillingCycleModifiable = isModifiable && isActiveSubscription()
|
||||||
dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable)
|
dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable)
|
||||||
chartDataUsagePreferenceController?.setBillingCycleModifiable(isBillingCycleModifiable)
|
chartDataUsagePreferenceController?.setBillingCycleModifiable(isBillingCycleModifiable)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isBillingCycleModifiable(): Boolean =
|
private fun isActiveSubscription(): Boolean =
|
||||||
billingCycleRepository.isModifiable(subId) &&
|
requireContext().requireSubscriptionManager().getActiveSubscriptionInfo(subId) != null
|
||||||
requireContext().getSystemService(SubscriptionManager::class.java)!!
|
|
||||||
.getActiveSubscriptionInfo(subId) != null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the chart and detail data when initial loaded or selected cycle changed.
|
* Updates the chart and detail data when initial loaded or selected cycle changed.
|
||||||
|
@@ -19,10 +19,15 @@ package com.android.settings.datausage.lib
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.INetworkManagementService
|
import android.os.INetworkManagementService
|
||||||
import android.os.ServiceManager
|
import android.os.ServiceManager
|
||||||
import android.telephony.TelephonyManager
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.annotation.OpenForTesting
|
import androidx.annotation.OpenForTesting
|
||||||
|
import com.android.settings.network.telephony.TelephonyRepository
|
||||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.conflate
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
@OpenForTesting
|
@OpenForTesting
|
||||||
open class BillingCycleRepository @JvmOverloads constructor(
|
open class BillingCycleRepository @JvmOverloads constructor(
|
||||||
@@ -31,12 +36,14 @@ open class BillingCycleRepository @JvmOverloads constructor(
|
|||||||
INetworkManagementService.Stub.asInterface(
|
INetworkManagementService.Stub.asInterface(
|
||||||
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)
|
ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE)
|
||||||
),
|
),
|
||||||
|
private val telephonyRepository: TelephonyRepository = TelephonyRepository(context),
|
||||||
) {
|
) {
|
||||||
private val userManager = context.userManager
|
private val userManager = context.userManager
|
||||||
private val telephonyManager = context.getSystemService(TelephonyManager::class.java)!!
|
|
||||||
|
|
||||||
fun isModifiable(subId: Int): Boolean =
|
fun isModifiableFlow(subId: Int): Flow<Boolean> =
|
||||||
isBandwidthControlEnabled() && userManager.isAdminUser && isDataEnabled(subId)
|
telephonyRepository.isDataEnabledFlow(subId).map { isDataEnabled ->
|
||||||
|
isDataEnabled && isBandwidthControlEnabled() && userManager.isAdminUser
|
||||||
|
}.conflate().flowOn(Dispatchers.Default)
|
||||||
|
|
||||||
open fun isBandwidthControlEnabled(): Boolean = try {
|
open fun isBandwidthControlEnabled(): Boolean = try {
|
||||||
networkService.isBandwidthControlEnabled
|
networkService.isBandwidthControlEnabled
|
||||||
@@ -45,10 +52,6 @@ open class BillingCycleRepository @JvmOverloads constructor(
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isDataEnabled(subId: Int): Boolean =
|
|
||||||
telephonyManager.createForSubscriptionId(subId)
|
|
||||||
.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "BillingCycleRepository"
|
private const val TAG = "BillingCycleRepository"
|
||||||
}
|
}
|
||||||
|
@@ -29,10 +29,12 @@ import kotlinx.coroutines.channels.ProducerScope
|
|||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.callbackFlow
|
import kotlinx.coroutines.flow.callbackFlow
|
||||||
|
import kotlinx.coroutines.flow.catch
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import kotlinx.coroutines.flow.flowOn
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
|
||||||
class TelephonyRepository(
|
class TelephonyRepository(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
@@ -64,19 +66,21 @@ class TelephonyRepository(
|
|||||||
telephonyManager.setMobileDataPolicyEnabled(policy, enabled)
|
telephonyManager.setMobileDataPolicyEnabled(policy, enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isDataEnabled(
|
fun isDataEnabledFlow(subId: Int): Flow<Boolean> {
|
||||||
subId: Int,
|
|
||||||
): Flow<Boolean> {
|
|
||||||
if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
|
if (!SubscriptionManager.isValidSubscriptionId(subId)) return flowOf(false)
|
||||||
|
|
||||||
Log.d(TAG, "register mobileDataEnabledFlow: [$subId]")
|
|
||||||
return context.mobileDataEnabledFlow(subId)
|
return context.mobileDataEnabledFlow(subId)
|
||||||
.map {
|
.map {
|
||||||
Log.d(TAG, "mobileDataEnabledFlow: receive mobile data [$subId] start")
|
|
||||||
val telephonyManager = context.telephonyManager(subId)
|
val telephonyManager = context.telephonyManager(subId)
|
||||||
telephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
telephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
||||||
.also { Log.d(TAG, "mobileDataEnabledFlow: [$subId] isDataEnabled(): $it") }
|
|
||||||
}
|
}
|
||||||
|
.catch {
|
||||||
|
Log.w(TAG, "[$subId] isDataEnabledFlow: exception", it)
|
||||||
|
emit(false)
|
||||||
|
}
|
||||||
|
.onEach { Log.d(TAG, "[$subId] isDataEnabledFlow: isDataEnabled() = $it") }
|
||||||
|
.conflate()
|
||||||
|
.flowOn(Dispatchers.Default)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setMobileData(
|
fun setMobileData(
|
||||||
@@ -100,6 +104,7 @@ class TelephonyRepository(
|
|||||||
wifiPickerTrackerHelper.setCarrierNetworkEnabled(enabled)
|
wifiPickerTrackerHelper.setCarrierNetworkEnabled(enabled)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
private const val TAG = "TelephonyRepository"
|
private const val TAG = "TelephonyRepository"
|
||||||
}
|
}
|
||||||
|
@@ -36,11 +36,11 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLifecycleOwner
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.res.vectorResource
|
import androidx.compose.ui.res.vectorResource
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
import androidx.lifecycle.LifecycleRegistry
|
import androidx.lifecycle.LifecycleRegistry
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
@@ -62,7 +62,6 @@ import com.android.settingslib.spaprivileged.settingsprovider.settingsGlobalBool
|
|||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.conflate
|
import kotlinx.coroutines.flow.conflate
|
||||||
import kotlinx.coroutines.flow.flowOf
|
import kotlinx.coroutines.flow.flowOf
|
||||||
@@ -207,7 +206,7 @@ fun MobileDataSectionImpl(
|
|||||||
}.collectAsStateWithLifecycle(initialValue = null)
|
}.collectAsStateWithLifecycle(initialValue = null)
|
||||||
|
|
||||||
val mobileDataStateChanged by remember(mobileDataSelectedId.intValue) {
|
val mobileDataStateChanged by remember(mobileDataSelectedId.intValue) {
|
||||||
TelephonyRepository(context).isDataEnabled(mobileDataSelectedId.intValue)
|
TelephonyRepository(context).isDataEnabledFlow(mobileDataSelectedId.intValue)
|
||||||
}.collectAsStateWithLifecycle(initialValue = false)
|
}.collectAsStateWithLifecycle(initialValue = false)
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
@@ -27,6 +27,8 @@ import androidx.test.core.app.ApplicationProvider
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import com.android.settings.R
|
import com.android.settings.R
|
||||||
import com.android.settings.datausage.lib.BillingCycleRepository
|
import com.android.settings.datausage.lib.BillingCycleRepository
|
||||||
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
|
import kotlinx.coroutines.flow.flowOf
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@@ -39,7 +41,9 @@ class BillingCyclePreferenceTest {
|
|||||||
@get:Rule
|
@get:Rule
|
||||||
val composeTestRule = createComposeRule()
|
val composeTestRule = createComposeRule()
|
||||||
|
|
||||||
private val mockBillingCycleRepository = mock<BillingCycleRepository>()
|
private val mockBillingCycleRepository = mock<BillingCycleRepository> {
|
||||||
|
on { isModifiableFlow(SUB_ID) } doReturn emptyFlow()
|
||||||
|
}
|
||||||
|
|
||||||
private val context: Context = ApplicationProvider.getApplicationContext()
|
private val context: Context = ApplicationProvider.getApplicationContext()
|
||||||
|
|
||||||
@@ -56,7 +60,7 @@ class BillingCyclePreferenceTest {
|
|||||||
@Test
|
@Test
|
||||||
fun setTemplate_modifiable_enabled() {
|
fun setTemplate_modifiable_enabled() {
|
||||||
mockBillingCycleRepository.stub {
|
mockBillingCycleRepository.stub {
|
||||||
on { isModifiable(SUB_ID) } doReturn true
|
on { isModifiableFlow(SUB_ID) } doReturn flowOf(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTemplate()
|
setTemplate()
|
||||||
@@ -67,7 +71,7 @@ class BillingCyclePreferenceTest {
|
|||||||
@Test
|
@Test
|
||||||
fun setTemplate_notModifiable_notEnabled() {
|
fun setTemplate_notModifiable_notEnabled() {
|
||||||
mockBillingCycleRepository.stub {
|
mockBillingCycleRepository.stub {
|
||||||
on { isModifiable(SUB_ID) } doReturn false
|
on { isModifiableFlow(SUB_ID) } doReturn flowOf(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
setTemplate()
|
setTemplate()
|
||||||
|
@@ -22,8 +22,10 @@ import android.os.UserManager
|
|||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import com.android.settingslib.spa.testutils.firstWithTimeoutOrNull
|
||||||
import com.android.settingslib.spaprivileged.framework.common.userManager
|
import com.android.settingslib.spaprivileged.framework.common.userManager
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.mockito.kotlin.doReturn
|
import org.mockito.kotlin.doReturn
|
||||||
@@ -55,43 +57,43 @@ class BillingCycleRepositoryTest {
|
|||||||
private val repository = BillingCycleRepository(context, mockNetworkManagementService)
|
private val repository = BillingCycleRepository(context, mockNetworkManagementService)
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun isModifiable_bandwidthControlDisabled_returnFalse() {
|
fun isModifiable_bandwidthControlDisabled_returnFalse() = runBlocking {
|
||||||
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(false)
|
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(false)
|
||||||
|
|
||||||
val modifiable = repository.isModifiable(SUB_ID)
|
val modifiable = repository.isModifiableFlow(SUB_ID).firstWithTimeoutOrNull()
|
||||||
|
|
||||||
assertThat(modifiable).isFalse()
|
assertThat(modifiable).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun isModifiable_notAdminUser_returnFalse() {
|
fun isModifiable_notAdminUser_returnFalse() = runBlocking {
|
||||||
whenever(mockUserManager.isAdminUser).thenReturn(false)
|
whenever(mockUserManager.isAdminUser).thenReturn(false)
|
||||||
|
|
||||||
val modifiable = repository.isModifiable(SUB_ID)
|
val modifiable = repository.isModifiableFlow(SUB_ID).firstWithTimeoutOrNull()
|
||||||
|
|
||||||
assertThat(modifiable).isFalse()
|
assertThat(modifiable).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun isModifiable_dataDisabled_returnFalse() {
|
fun isModifiable_dataDisabled_returnFalse() = runBlocking {
|
||||||
whenever(
|
whenever(
|
||||||
mockTelephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
mockTelephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
||||||
).thenReturn(false)
|
).thenReturn(false)
|
||||||
|
|
||||||
val modifiable = repository.isModifiable(SUB_ID)
|
val modifiable = repository.isModifiableFlow(SUB_ID).firstWithTimeoutOrNull()
|
||||||
|
|
||||||
assertThat(modifiable).isFalse()
|
assertThat(modifiable).isFalse()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun isModifiable_meetAllRequirements_returnTrue() {
|
fun isModifiable_meetAllRequirements_returnTrue() = runBlocking {
|
||||||
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(true)
|
whenever(mockNetworkManagementService.isBandwidthControlEnabled).thenReturn(true)
|
||||||
whenever(mockUserManager.isAdminUser).thenReturn(true)
|
whenever(mockUserManager.isAdminUser).thenReturn(true)
|
||||||
whenever(
|
whenever(
|
||||||
mockTelephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
mockTelephonyManager.isDataEnabledForReason(TelephonyManager.DATA_ENABLED_REASON_USER)
|
||||||
).thenReturn(true)
|
).thenReturn(true)
|
||||||
|
|
||||||
val modifiable = repository.isModifiable(SUB_ID)
|
val modifiable = repository.isModifiableFlow(SUB_ID).firstWithTimeoutOrNull()
|
||||||
|
|
||||||
assertThat(modifiable).isTrue()
|
assertThat(modifiable).isTrue()
|
||||||
}
|
}
|
||||||
|
@@ -93,7 +93,7 @@ class TelephonyRepositoryTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun isDataEnabled_invalidSub_returnFalse() = runBlocking {
|
fun isDataEnabled_invalidSub_returnFalse() = runBlocking {
|
||||||
val state = repository.isDataEnabled(
|
val state = repository.isDataEnabledFlow(
|
||||||
subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
|
subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -108,9 +108,7 @@ class TelephonyRepositoryTest {
|
|||||||
} doReturn true
|
} doReturn true
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = repository.isDataEnabled(
|
val state = repository.isDataEnabledFlow(subId = SUB_ID)
|
||||||
subId = SUB_ID,
|
|
||||||
)
|
|
||||||
|
|
||||||
assertThat(state.firstWithTimeoutOrNull()).isTrue()
|
assertThat(state.firstWithTimeoutOrNull()).isTrue()
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user