Merge "[SB Refactor] Show space between wifi and RAT icon if needed." into udc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
46c1fea283
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupR
|
||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
|
||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractorImpl
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileUiAdapter
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxy
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.MobileMappingsProxyImpl
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.SubscriptionManagerProxy
|
||||
@@ -53,6 +54,9 @@ import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.multibindings.ClassKey
|
||||
import dagger.multibindings.IntoMap
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import java.util.function.Supplier
|
||||
import javax.inject.Named
|
||||
|
||||
@Module
|
||||
abstract class StatusBarPipelineModule {
|
||||
@@ -113,6 +117,17 @@ abstract class StatusBarPipelineModule {
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@SysUISingleton
|
||||
@Named(FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON)
|
||||
fun provideFirstMobileSubShowingNetworkTypeIconProvider(
|
||||
mobileIconsViewModel: MobileIconsViewModel,
|
||||
): Supplier<Flow<Boolean>> {
|
||||
return Supplier<Flow<Boolean>> {
|
||||
mobileIconsViewModel.firstMobileSubShowingNetworkTypeIcon
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@SysUISingleton
|
||||
@WifiInputLog
|
||||
@@ -168,5 +183,8 @@ abstract class StatusBarPipelineModule {
|
||||
fun provideVerboseMobileViewLogBuffer(factory: LogBufferFactory): LogBuffer {
|
||||
return factory.create("VerboseMobileViewLog", 100)
|
||||
}
|
||||
|
||||
const val FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON =
|
||||
"FirstMobileSubShowingNetworkTypeIcon"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapLatest
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -63,22 +66,36 @@ constructor(
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), listOf())
|
||||
|
||||
private val firstMobileSubViewModel: StateFlow<MobileIconViewModelCommon?> =
|
||||
subscriptionIdsFlow
|
||||
.map {
|
||||
if (it.isEmpty()) {
|
||||
null
|
||||
} else {
|
||||
// Mobile icons get reversed by [StatusBarIconController], so the last element
|
||||
// in this list will show up visually first.
|
||||
commonViewModelForSub(it.last())
|
||||
}
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), null)
|
||||
|
||||
/**
|
||||
* A flow that emits `true` if the mobile sub that's displayed first visually is showing its
|
||||
* network type icon and `false` otherwise.
|
||||
*/
|
||||
val firstMobileSubShowingNetworkTypeIcon: StateFlow<Boolean> =
|
||||
firstMobileSubViewModel
|
||||
.flatMapLatest { firstMobileSubViewModel ->
|
||||
firstMobileSubViewModel?.networkTypeIcon?.map { it != null } ?: flowOf(false)
|
||||
}
|
||||
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
|
||||
|
||||
init {
|
||||
scope.launch { subscriptionIdsFlow.collect { removeInvalidModelsFromCache(it) } }
|
||||
}
|
||||
|
||||
fun viewModelForSub(subId: Int, location: StatusBarLocation): LocationBasedMobileViewModel {
|
||||
val common =
|
||||
mobileIconSubIdCache[subId]
|
||||
?: MobileIconViewModel(
|
||||
subId,
|
||||
interactor.createMobileConnectionInteractorForSubId(subId),
|
||||
airplaneModeInteractor,
|
||||
constants,
|
||||
scope,
|
||||
)
|
||||
.also { mobileIconSubIdCache[subId] = it }
|
||||
|
||||
val common = commonViewModelForSub(subId)
|
||||
return LocationBasedMobileViewModel.viewModelForLocation(
|
||||
common,
|
||||
statusBarPipelineFlags,
|
||||
@@ -87,6 +104,18 @@ constructor(
|
||||
)
|
||||
}
|
||||
|
||||
private fun commonViewModelForSub(subId: Int): MobileIconViewModelCommon {
|
||||
return mobileIconSubIdCache[subId]
|
||||
?: MobileIconViewModel(
|
||||
subId,
|
||||
interactor.createMobileConnectionInteractorForSubId(subId),
|
||||
airplaneModeInteractor,
|
||||
constants,
|
||||
scope,
|
||||
)
|
||||
.also { mobileIconSubIdCache[subId] = it }
|
||||
}
|
||||
|
||||
private fun removeInvalidModelsFromCache(subIds: List<Int>) {
|
||||
val subIdsToRemove = mobileIconSubIdCache.keys.filter { !subIds.contains(it) }
|
||||
subIdsToRemove.forEach { mobileIconSubIdCache.remove(it) }
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWi
|
||||
import kotlinx.coroutines.InternalCoroutinesApi
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -64,6 +63,7 @@ object WifiViewBinder {
|
||||
val activityOutView = view.requireViewById<ImageView>(R.id.wifi_out)
|
||||
val activityContainerView = view.requireViewById<View>(R.id.inout_container)
|
||||
val airplaneSpacer = view.requireViewById<View>(R.id.wifi_airplane_spacer)
|
||||
val signalSpacer = view.requireViewById<View>(R.id.wifi_signal_spacer)
|
||||
|
||||
view.isVisible = true
|
||||
iconView.isVisible = true
|
||||
@@ -133,6 +133,12 @@ object WifiViewBinder {
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.isSignalSpacerVisible.distinctUntilChanged().collect { visible ->
|
||||
signalSpacer.isVisible = visible
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
awaitCancellation()
|
||||
} finally {
|
||||
|
||||
@@ -30,8 +30,8 @@ import com.android.systemui.log.table.logDiffsForTable
|
||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
|
||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
|
||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
|
||||
import com.android.systemui.statusbar.pipeline.dagger.StatusBarPipelineModule.Companion.FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON
|
||||
import com.android.systemui.statusbar.pipeline.dagger.WifiTableLog
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
|
||||
@@ -39,7 +39,9 @@ import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiIntera
|
||||
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
|
||||
import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon
|
||||
import java.util.function.Supplier
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Named
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -53,24 +55,24 @@ import kotlinx.coroutines.flow.stateIn
|
||||
/**
|
||||
* Models the UI state for the status bar wifi icon.
|
||||
*
|
||||
* This class exposes three view models, one per status bar location: [home], [keyguard], and [qs].
|
||||
* In order to get the UI state for the wifi icon, you must use one of those view models (whichever
|
||||
* is correct for your location).
|
||||
*
|
||||
* Internally, this class maintains the current state of the wifi icon and notifies those three view
|
||||
* models of any changes.
|
||||
* This is a singleton so that we don't have duplicate logs and should *not* be used directly to
|
||||
* control views. Instead, use an instance of [LocationBasedWifiViewModel]. See
|
||||
* [LocationBasedWifiViewModel.viewModelForLocation].
|
||||
*/
|
||||
@SysUISingleton
|
||||
class WifiViewModel
|
||||
@Inject
|
||||
constructor(
|
||||
airplaneModeViewModel: AirplaneModeViewModel,
|
||||
// TODO(b/238425913): The wifi icon shouldn't need to consume mobile information. A
|
||||
// container-level view model should do the work instead.
|
||||
@Named(FIRST_MOBILE_SUB_SHOWING_NETWORK_TYPE_ICON)
|
||||
shouldShowSignalSpacerProvider: Supplier<Flow<Boolean>>,
|
||||
connectivityConstants: ConnectivityConstants,
|
||||
private val context: Context,
|
||||
@WifiTableLog wifiTableLogBuffer: TableLogBuffer,
|
||||
interactor: WifiInteractor,
|
||||
@Application private val scope: CoroutineScope,
|
||||
statusBarPipelineFlags: StatusBarPipelineFlags,
|
||||
wifiConstants: WifiConstants,
|
||||
) : WifiViewModelCommon {
|
||||
/** Returns the icon to use based on the given network. */
|
||||
@@ -183,6 +185,8 @@ constructor(
|
||||
override val isAirplaneSpacerVisible: Flow<Boolean> =
|
||||
airplaneModeViewModel.isAirplaneModeIconVisible
|
||||
|
||||
override val isSignalSpacerVisible: Flow<Boolean> = shouldShowSignalSpacerProvider.get()
|
||||
|
||||
companion object {
|
||||
@StringRes
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -39,4 +39,7 @@ interface WifiViewModelCommon {
|
||||
|
||||
/** True if the airplane spacer view should be visible. */
|
||||
val isAirplaneSpacerVisible: Flow<Boolean>
|
||||
|
||||
/** True if the spacer between the wifi icon and the RAT icon should be visible. */
|
||||
val isSignalSpacerVisible: Flow<Boolean>
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ class FakeMobileIconsInteractor(
|
||||
FIVE_G_OVERRIDE_KEY to TelephonyIcons.NR_5G,
|
||||
)
|
||||
|
||||
private val interactorCache: MutableMap<Int, FakeMobileIconInteractor> = mutableMapOf()
|
||||
|
||||
override val isDefaultConnectionFailed = MutableStateFlow(false)
|
||||
|
||||
override val filteredSubscriptions = MutableStateFlow<List<SubscriptionModel>>(listOf())
|
||||
@@ -75,7 +77,15 @@ class FakeMobileIconsInteractor(
|
||||
|
||||
/** Always returns a new fake interactor */
|
||||
override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor {
|
||||
return FakeMobileIconInteractor(tableLogBuffer)
|
||||
return FakeMobileIconInteractor(tableLogBuffer).also { interactorCache[subId] = it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the most recently created interactor for the given subId, or null if an interactor
|
||||
* has never been created for that sub.
|
||||
*/
|
||||
fun getInteractorForSubId(subId: Int): FakeMobileIconInteractor? {
|
||||
return interactorCache[subId]
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
|
||||
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.settingslib.mobile.TelephonyIcons
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
@@ -24,6 +25,7 @@ import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirp
|
||||
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||
import com.android.systemui.statusbar.pipeline.mobile.data.model.SubscriptionModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
|
||||
import com.android.systemui.statusbar.pipeline.mobile.domain.model.NetworkTypeIconModel
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.MobileViewLogger
|
||||
import com.android.systemui.statusbar.pipeline.mobile.ui.VerboseMobileViewLogger
|
||||
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
|
||||
@@ -135,8 +137,179 @@ class MobileIconsViewModelTest : SysuiTestCase() {
|
||||
assertThat(underTest.mobileIconSubIdCache).containsExactly(2, model2.commonImpl)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_noSubs_false() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = emptyList()
|
||||
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_oneSub_notShowingRat_false() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1)
|
||||
// The unknown icon group doesn't show a RAT
|
||||
interactor.getInteractorForSubId(1)!!.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_oneSub_showingRat_true() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1)
|
||||
// The 3G icon group will show a RAT
|
||||
interactor.getInteractorForSubId(1)!!.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)
|
||||
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_updatesAsSubUpdates() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1)
|
||||
val sub1Interactor = interactor.getInteractorForSubId(1)!!
|
||||
|
||||
sub1Interactor.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
sub1Interactor.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
sub1Interactor.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.LTE)
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_multipleSubs_lastSubNotShowingRat_false() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||
interactor.getInteractorForSubId(1)?.networkTypeIconGroup?.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)
|
||||
interactor.getInteractorForSubId(2)!!.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_multipleSubs_lastSubShowingRat_true() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||
interactor.getInteractorForSubId(1)?.networkTypeIconGroup?.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
interactor.getInteractorForSubId(2)!!.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)
|
||||
|
||||
assertThat(latest).isTrue()
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_subListUpdates_valAlsoUpdates() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||
interactor.getInteractorForSubId(1)?.networkTypeIconGroup?.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
interactor.getInteractorForSubId(2)!!.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)
|
||||
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
// WHEN the sub list gets new subscriptions where the last subscription is not showing
|
||||
// the network type icon
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2, SUB_3)
|
||||
interactor.getInteractorForSubId(3)!!.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
|
||||
// THEN the flow updates
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstMobileSubShowingNetworkTypeIcon_subListReorders_valAlsoUpdates() =
|
||||
testScope.runTest {
|
||||
var latest: Boolean? = null
|
||||
val job =
|
||||
underTest.firstMobileSubShowingNetworkTypeIcon.onEach { latest = it }.launchIn(this)
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||
// Immediately switch the order so that we've created both interactors
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_2, SUB_1)
|
||||
val sub1Interactor = interactor.getInteractorForSubId(1)!!
|
||||
val sub2Interactor = interactor.getInteractorForSubId(2)!!
|
||||
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||
sub1Interactor.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.UNKNOWN)
|
||||
sub2Interactor.networkTypeIconGroup.value =
|
||||
NetworkTypeIconModel.DefaultIcon(TelephonyIcons.THREE_G)
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
// WHEN sub1 becomes last and sub1 has no network type icon
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_2, SUB_1)
|
||||
|
||||
// THEN the flow updates
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
// WHEN sub2 becomes last and sub2 has a network type icon
|
||||
interactor.filteredSubscriptions.value = listOf(SUB_1, SUB_2)
|
||||
|
||||
// THEN the flow updates
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val SUB_1 = SubscriptionModel(subscriptionId = 1, isOpportunistic = false)
|
||||
private val SUB_2 = SubscriptionModel(subscriptionId = 2, isOpportunistic = false)
|
||||
private val SUB_3 = SubscriptionModel(subscriptionId = 3, isOpportunistic = false)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ import com.android.systemui.util.mockito.whenever
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
@@ -98,12 +99,12 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() {
|
||||
val viewModelCommon =
|
||||
WifiViewModel(
|
||||
airplaneModeViewModel,
|
||||
shouldShowSignalSpacerProvider = { MutableStateFlow(false) },
|
||||
connectivityConstants,
|
||||
context,
|
||||
tableLogBuffer,
|
||||
interactor,
|
||||
scope,
|
||||
statusBarPipelineFlags,
|
||||
wifiConstants,
|
||||
)
|
||||
viewModel =
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.android.systemui.log.table.TableLogBuffer
|
||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS
|
||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS
|
||||
import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository
|
||||
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
|
||||
import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel
|
||||
@@ -46,6 +45,7 @@ import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.yield
|
||||
@@ -66,7 +66,6 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
|
||||
|
||||
private lateinit var underTest: WifiViewModel
|
||||
|
||||
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
|
||||
@Mock private lateinit var tableLogBuffer: TableLogBuffer
|
||||
@Mock private lateinit var connectivityConstants: ConnectivityConstants
|
||||
@Mock private lateinit var wifiConstants: WifiConstants
|
||||
@@ -121,12 +120,12 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase
|
||||
underTest =
|
||||
WifiViewModel(
|
||||
airplaneModeViewModel,
|
||||
shouldShowSignalSpacerProvider = { MutableStateFlow(false) },
|
||||
connectivityConstants,
|
||||
context,
|
||||
tableLogBuffer,
|
||||
interactor,
|
||||
scope,
|
||||
statusBarPipelineFlags,
|
||||
wifiConstants,
|
||||
)
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWi
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.runBlocking
|
||||
@@ -53,7 +53,6 @@ import org.mockito.Mockito.`when` as whenever
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@SmallTest
|
||||
class WifiViewModelTest : SysuiTestCase() {
|
||||
|
||||
@@ -68,6 +67,7 @@ class WifiViewModelTest : SysuiTestCase() {
|
||||
private lateinit var wifiRepository: FakeWifiRepository
|
||||
private lateinit var interactor: WifiInteractor
|
||||
private lateinit var airplaneModeViewModel: AirplaneModeViewModel
|
||||
private val shouldShowSignalSpacerProviderFlow = MutableStateFlow(false)
|
||||
private lateinit var scope: CoroutineScope
|
||||
|
||||
@Before
|
||||
@@ -473,6 +473,34 @@ class WifiViewModelTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun signalSpacer_firstSubNotShowingNetworkTypeIcon_outputsFalse() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: Boolean? = null
|
||||
val job = underTest.isSignalSpacerVisible.onEach { latest = it }.launchIn(this)
|
||||
|
||||
shouldShowSignalSpacerProviderFlow.value = false
|
||||
yield()
|
||||
|
||||
assertThat(latest).isFalse()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun signalSpacer_firstSubIsShowingNetworkTypeIcon_outputsTrue() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var latest: Boolean? = null
|
||||
val job = underTest.isSignalSpacerVisible.onEach { latest = it }.launchIn(this)
|
||||
|
||||
shouldShowSignalSpacerProviderFlow.value = true
|
||||
yield()
|
||||
|
||||
assertThat(latest).isTrue()
|
||||
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
private fun createAndSetViewModel() {
|
||||
// [WifiViewModel] creates its flows as soon as it's instantiated, and some of those flow
|
||||
// creations rely on certain config values that we mock out in individual tests. This method
|
||||
@@ -480,12 +508,12 @@ class WifiViewModelTest : SysuiTestCase() {
|
||||
underTest =
|
||||
WifiViewModel(
|
||||
airplaneModeViewModel,
|
||||
{ shouldShowSignalSpacerProviderFlow },
|
||||
connectivityConstants,
|
||||
context,
|
||||
tableLogBuffer,
|
||||
interactor,
|
||||
scope,
|
||||
statusBarPipelineFlags,
|
||||
wifiConstants,
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user