[SB Refactor] Migrate mobile's state.visible to the new pipeline.

StatusBarMobileView uses `MobileIconState.visible` to determine its
visibility status. Following all the inputs to `visible`, then
`visible = hasMobileData && !airplaneMode && !forceHiddenByTuning`. This
CL implements that boolean logic.

Bug: 238425913
Fixes: 267786582
Test: manual: turn on airplane mode and verify mobile triangle is hidden
every where. Turn off airplane mode and verify triangle re-appears.
Test: `adb shell pm enable com.android.systemui/.tuner.TunerActivity`
then Settings > System > System UI Tuner > Status bar > Toggle the
mobile
on/off and see the mobile icon toggle as well
Test: atest MobileIconViewModelTest

Change-Id: I5986ba477ba5172480ab4a5f7b9900259a8466ea
This commit is contained in:
Caitlin Shkuratov
2023-02-06 20:42:11 +00:00
parent 83e7763535
commit 2def6f9adf
13 changed files with 319 additions and 30 deletions

View File

@@ -111,6 +111,9 @@ interface MobileIconInteractor {
/** Based on [CarrierConfigManager.KEY_INFLATE_SIGNAL_STRENGTH_BOOL], either 4 or 5 */
val numberOfLevels: StateFlow<Int>
/** See [MobileIconsInteractor.isForceHidden]. */
val isForceHidden: Flow<Boolean>
}
/** Interactor for a single mobile connection. This connection _should_ have one subscription ID */
@@ -126,6 +129,7 @@ class MobileIconInteractorImpl(
defaultMobileIconGroup: StateFlow<MobileIconGroup>,
defaultDataSubId: StateFlow<Int>,
override val isDefaultConnectionFailed: StateFlow<Boolean>,
override val isForceHidden: Flow<Boolean>,
connectionRepository: MobileConnectionRepository,
) : MobileIconInteractor {
private val connectionInfo = connectionRepository.connectionInfo

View File

@@ -32,6 +32,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConn
import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository
import com.android.systemui.util.CarrierConfigTracker
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -45,8 +47,8 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.transformLatest
@@ -91,6 +93,10 @@ interface MobileIconsInteractor {
val isDefaultConnectionFailed: StateFlow<Boolean>
/** True once the user has been set up */
val isUserSetup: StateFlow<Boolean>
/** True if we're configured to force-hide the mobile icons and false otherwise. */
val isForceHidden: Flow<Boolean>
/**
* Vends out a [MobileIconInteractor] tracking the [MobileConnectionRepository] for the given
* subId. Will throw if the ID is invalid
@@ -108,6 +114,7 @@ constructor(
private val carrierConfigTracker: CarrierConfigTracker,
private val logger: ConnectivityPipelineLogger,
@MobileSummaryLog private val tableLogger: TableLogBuffer,
connectivityRepository: ConnectivityRepository,
userSetupRepo: UserSetupRepository,
@Application private val scope: CoroutineScope,
) : MobileIconsInteractor {
@@ -291,6 +298,11 @@ constructor(
override val isUserSetup: StateFlow<Boolean> = userSetupRepo.isUserSetupFlow
override val isForceHidden: Flow<Boolean> =
connectivityRepository.forceHiddenSlots
.map { it.contains(ConnectivitySlot.MOBILE) }
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
/** Vends out new [MobileIconInteractor] for a particular subId */
override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor =
MobileIconInteractorImpl(
@@ -303,6 +315,7 @@ constructor(
defaultMobileIconGroup,
defaultDataSubId,
isDefaultConnectionFailed,
isForceHidden,
mobileConnectionsRepo.getRepoForSubId(subId),
)

View File

@@ -91,6 +91,8 @@ object MobileIconBinder {
}
}
launch { viewModel.isVisible.collect { isVisible -> view.isVisible = isVisible } }
// Set the icon for the triangle
launch {
viewModel.icon.distinctUntilChanged().collect { icon ->
@@ -153,8 +155,7 @@ object MobileIconBinder {
return object : ModernStatusBarViewBinding {
override fun getShouldIconBeVisible(): Boolean {
// If this view model exists, then the icon should be visible.
return true
return viewModel.isVisible.value
}
override fun onVisibilityStateChanged(@StatusBarIconView.VisibleState state: Int) {

View File

@@ -22,6 +22,7 @@ import com.android.settingslib.graph.SignalDrawable
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
@@ -42,6 +43,8 @@ import kotlinx.coroutines.flow.stateIn
/** Common interface for all of the location-based mobile icon view models. */
interface MobileIconViewModelCommon {
val subscriptionId: Int
/** True if this view should be visible at all. */
val isVisible: StateFlow<Boolean>
val icon: Flow<SignalIconModel>
val contentDescription: Flow<ContentDescription>
val roaming: Flow<Boolean>
@@ -71,6 +74,7 @@ class MobileIconViewModel
constructor(
override val subscriptionId: Int,
iconInteractor: MobileIconInteractor,
airplaneModeInteractor: AirplaneModeInteractor,
constants: ConnectivityConstants,
scope: CoroutineScope,
) : MobileIconViewModelCommon {
@@ -78,6 +82,26 @@ constructor(
private val showExclamationMark: Flow<Boolean> =
iconInteractor.isDefaultDataEnabled.mapLatest { !it }
override val isVisible: StateFlow<Boolean> =
if (!constants.hasDataCapabilities) {
flowOf(false)
} else {
combine(
airplaneModeInteractor.isAirplaneMode,
iconInteractor.isForceHidden,
) { isAirplaneMode, isForceHidden ->
!isAirplaneMode && !isForceHidden
}
}
.distinctUntilChanged()
.logDiffsForTable(
iconInteractor.tableLogBuffer,
columnPrefix = "",
columnName = "visible",
initialValue = false,
)
.stateIn(scope, SharingStarted.WhileSubscribed(), false)
override val icon: Flow<SignalIconModel> = run {
val initial = SignalIconModel.createEmptyState(iconInteractor.numberOfLevels.value)
combine(

View File

@@ -17,9 +17,11 @@
package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel
import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.statusbar.phone.StatusBarLocation
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.MobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernStatusBarMobileView
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
@@ -39,6 +41,7 @@ class MobileIconsViewModel
constructor(
val subscriptionIdsFlow: StateFlow<List<Int>>,
private val interactor: MobileIconsInteractor,
private val airplaneModeInteractor: AirplaneModeInteractor,
private val logger: ConnectivityPipelineLogger,
private val constants: ConnectivityConstants,
@Application private val scope: CoroutineScope,
@@ -56,6 +59,7 @@ constructor(
?: MobileIconViewModel(
subId,
interactor.createMobileConnectionInteractorForSubId(subId),
airplaneModeInteractor,
constants,
scope,
)
@@ -73,10 +77,12 @@ constructor(
subIdsToRemove.forEach { mobileIconSubIdCache.remove(it) }
}
@SysUISingleton
class Factory
@Inject
constructor(
private val interactor: MobileIconsInteractor,
private val airplaneModeInteractor: AirplaneModeInteractor,
private val logger: ConnectivityPipelineLogger,
private val constants: ConnectivityConstants,
@Application private val scope: CoroutineScope,
@@ -86,6 +92,7 @@ constructor(
return MobileIconsViewModel(
subscriptionIdsFlow,
interactor,
airplaneModeInteractor,
logger,
constants,
scope,

View File

@@ -71,6 +71,8 @@ class FakeMobileIconInteractor(
private val _numberOfLevels = MutableStateFlow(DEFAULT_NUM_LEVELS)
override val numberOfLevels = _numberOfLevels
override val isForceHidden = MutableStateFlow(false)
fun setIconGroup(group: SignalIcon.MobileIconGroup) {
_iconGroup.value = group
}

View File

@@ -73,6 +73,8 @@ class FakeMobileIconsInteractor(
private val _isUserSetup = MutableStateFlow(true)
override val isUserSetup = _isUserSetup
override val isForceHidden = MutableStateFlow(false)
/** Always returns a new fake interactor */
override fun createMobileConnectionInteractorForSubId(subId: Int): MobileIconInteractor {
return FakeMobileIconInteractor(tableLogBuffer)

View File

@@ -66,6 +66,7 @@ class MobileIconInteractorTest : SysuiTestCase() {
mobileIconsInteractor.defaultMobileIconGroup,
mobileIconsInteractor.defaultDataSubId,
mobileIconsInteractor.isDefaultConnectionFailed,
mobileIconsInteractor.isForceHidden,
connectionRepository,
)
}
@@ -550,6 +551,21 @@ class MobileIconInteractorTest : SysuiTestCase() {
job.cancel()
}
@Test
fun isForceHidden_matchesParent() =
runBlocking(IMMEDIATE) {
var latest: Boolean? = null
val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
mobileIconsInteractor.isForceHidden.value = true
assertThat(latest).isTrue()
mobileIconsInteractor.isForceHidden.value = false
assertThat(latest).isFalse()
job.cancel()
}
companion object {
private val IMMEDIATE = Dispatchers.Main.immediate

View File

@@ -27,6 +27,8 @@ import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobile
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeMobileConnectionsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.util.CarrierConfigTracker
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
@@ -50,6 +52,7 @@ import org.mockito.MockitoAnnotations
@SmallTest
class MobileIconsInteractorTest : SysuiTestCase() {
private lateinit var underTest: MobileIconsInteractor
private lateinit var connectivityRepository: FakeConnectivityRepository
private lateinit var connectionsRepository: FakeMobileConnectionsRepository
private val userSetupRepository = FakeUserSetupRepository()
private val mobileMappingsProxy = FakeMobileMappingsProxy()
@@ -63,6 +66,8 @@ class MobileIconsInteractorTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
connectivityRepository = FakeConnectivityRepository()
connectionsRepository = FakeMobileConnectionsRepository(mobileMappingsProxy, tableLogBuffer)
connectionsRepository.setMobileConnectionRepositoryMap(
mapOf(
@@ -80,6 +85,7 @@ class MobileIconsInteractorTest : SysuiTestCase() {
carrierConfigTracker,
logger = mock(),
tableLogger = mock(),
connectivityRepository,
userSetupRepository,
testScope.backgroundScope,
)
@@ -610,6 +616,32 @@ class MobileIconsInteractorTest : SysuiTestCase() {
job.cancel()
}
@Test
fun isForceHidden_repoHasMobileHidden_true() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.MOBILE))
assertThat(latest).isTrue()
job.cancel()
}
@Test
fun isForceHidden_repoDoesNotHaveMobileHidden_false() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isForceHidden.onEach { latest = it }.launchIn(this)
connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI))
assertThat(latest).isFalse()
job.cancel()
}
companion object {
private val tableLogBuffer =
TableLogBuffer(8, "MobileIconsInteractorTest", FakeSystemClock())

View File

@@ -29,11 +29,14 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.statusbar.StatusBarIconView
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.mobile.domain.interactor.FakeMobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.LocationBasedMobileViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.QsMobileIconViewModel
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,28 +61,36 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var tableLogBuffer: TableLogBuffer
@Mock private lateinit var constants: ConnectivityConstants
private lateinit var interactor: FakeMobileIconInteractor
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
private lateinit var viewModelCommon: MobileIconViewModel
private lateinit var viewModel: LocationBasedMobileViewModel
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
// This line was necessary to make the onDarkChanged and setStaticDrawableColor tests pass.
// But, it maybe *shouldn't* be necessary.
whenever(constants.hasDataCapabilities).thenReturn(true)
testableLooper = TestableLooper.get(this)
val interactor = FakeMobileIconInteractor(tableLogBuffer)
val viewModelCommon =
MobileIconViewModel(
subscriptionId = 1,
interactor,
constants,
testScope.backgroundScope,
airplaneModeRepository = FakeAirplaneModeRepository()
airplaneModeInteractor =
AirplaneModeInteractor(
airplaneModeRepository,
FakeConnectivityRepository(),
)
viewModel = QsMobileIconViewModel(viewModelCommon, statusBarPipelineFlags)
interactor = FakeMobileIconInteractor(tableLogBuffer)
createViewModel()
}
// Note: The following tests are more like integration tests, since they stand up a full
// [WifiViewModel] and test the interactions between the view, view-binder, and view-model.
// [MobileIconViewModel] and test the interactions between the view, view-binder, and
// view-model.
@Test
fun setVisibleState_icon_iconShownDotHidden() {
@@ -127,7 +138,25 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
}
@Test
fun isIconVisible_alwaysTrue() {
fun isIconVisible_noData_outputsFalse() {
whenever(constants.hasDataCapabilities).thenReturn(false)
createViewModel()
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
assertThat(view.isIconVisible).isFalse()
ViewUtils.detachView(view)
}
@Test
fun isIconVisible_hasData_outputsTrue() {
whenever(constants.hasDataCapabilities).thenReturn(true)
createViewModel()
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
ViewUtils.attachView(view)
@@ -138,6 +167,34 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
ViewUtils.detachView(view)
}
@Test
fun isIconVisible_notAirplaneMode_outputsTrue() {
airplaneModeRepository.setIsAirplaneMode(false)
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
assertThat(view.isIconVisible).isTrue()
ViewUtils.detachView(view)
}
@Test
fun isIconVisible_airplaneMode_outputsTrue() {
airplaneModeRepository.setIsAirplaneMode(true)
val view = ModernStatusBarMobileView.constructAndBind(context, SLOT_NAME, viewModel)
ViewUtils.attachView(view)
testableLooper.processAllMessages()
assertThat(view.isIconVisible).isFalse()
ViewUtils.detachView(view)
}
@Test
fun onDarkChanged_iconHasNewColor() {
whenever(statusBarPipelineFlags.useDebugColoring()).thenReturn(false)
@@ -181,6 +238,18 @@ class ModernStatusBarMobileViewTest : SysuiTestCase() {
private fun View.getDotView(): View {
return this.requireViewById(R.id.status_bar_dot)
}
private fun createViewModel() {
viewModelCommon =
MobileIconViewModel(
subscriptionId = 1,
interactor,
airplaneModeInteractor,
constants,
testScope.backgroundScope,
)
viewModel = QsMobileIconViewModel(viewModelCommon, statusBarPipelineFlags)
}
}
private const val SLOT_NAME = "TestSlotName"

View File

@@ -21,10 +21,13 @@ import com.android.settingslib.mobile.TelephonyIcons
import com.android.systemui.SysuiTestCase
import com.android.systemui.log.table.TableLogBuffer
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.mobile.domain.interactor.FakeMobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconViewModelTest.Companion.defaultSignal
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.launchIn
@@ -46,6 +49,7 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
private lateinit var qsIcon: QsMobileIconViewModel
private lateinit var keyguardIcon: KeyguardMobileIconViewModel
private lateinit var interactor: FakeMobileIconInteractor
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var constants: ConnectivityConstants
@Mock private lateinit var tableLogBuffer: TableLogBuffer
@@ -56,6 +60,11 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
airplaneModeInteractor =
AirplaneModeInteractor(
FakeAirplaneModeRepository(),
FakeConnectivityRepository(),
)
interactor = FakeMobileIconInteractor(tableLogBuffer)
interactor.apply {
setLevel(1)
@@ -66,7 +75,14 @@ class LocationBasedMobileIconViewModelTest : SysuiTestCase() {
setNumberOfLevels(4)
isDataConnected.value = true
}
commonImpl = MobileIconViewModel(SUB_1_ID, interactor, constants, testScope.backgroundScope)
commonImpl =
MobileIconViewModel(
SUB_1_ID,
interactor,
airplaneModeInteractor,
constants,
testScope.backgroundScope,
)
homeIcon = HomeMobileIconViewModel(commonImpl, statusBarPipelineFlags)
qsIcon = QsMobileIconViewModel(commonImpl, statusBarPipelineFlags)

View File

@@ -24,10 +24,13 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.ContentDescription
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.log.table.TableLogBuffer
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.mobile.domain.interactor.FakeMobileIconInteractor
import com.android.systemui.statusbar.pipeline.mobile.ui.model.SignalIconModel
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.data.model.DataActivityModel
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -48,6 +51,8 @@ import org.mockito.MockitoAnnotations
class MobileIconViewModelTest : SysuiTestCase() {
private lateinit var underTest: MobileIconViewModel
private lateinit var interactor: FakeMobileIconInteractor
private lateinit var airplaneModeRepository: FakeAirplaneModeRepository
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@Mock private lateinit var constants: ConnectivityConstants
@Mock private lateinit var tableLogBuffer: TableLogBuffer
@@ -57,6 +62,15 @@ class MobileIconViewModelTest : SysuiTestCase() {
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
whenever(constants.hasDataCapabilities).thenReturn(true)
airplaneModeRepository = FakeAirplaneModeRepository()
airplaneModeInteractor =
AirplaneModeInteractor(
airplaneModeRepository,
FakeConnectivityRepository(),
)
interactor = FakeMobileIconInteractor(tableLogBuffer)
interactor.apply {
setLevel(1)
@@ -67,9 +81,89 @@ class MobileIconViewModelTest : SysuiTestCase() {
setNumberOfLevels(4)
isDataConnected.value = true
}
underTest = MobileIconViewModel(SUB_1_ID, interactor, constants, testScope.backgroundScope)
createAndSetViewModel()
}
@Test
fun isVisible_notDataCapable_alwaysFalse() =
testScope.runTest {
// Create a new view model here so the constants are properly read
whenever(constants.hasDataCapabilities).thenReturn(false)
createAndSetViewModel()
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
assertThat(latest).isFalse()
job.cancel()
}
@Test
fun isVisible_notAirplane_notForceHidden_true() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
airplaneModeRepository.setIsAirplaneMode(false)
interactor.isForceHidden.value = false
assertThat(latest).isTrue()
job.cancel()
}
@Test
fun isVisible_airplane_false() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
airplaneModeRepository.setIsAirplaneMode(true)
interactor.isForceHidden.value = false
assertThat(latest).isFalse()
job.cancel()
}
@Test
fun isVisible_forceHidden_false() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
airplaneModeRepository.setIsAirplaneMode(false)
interactor.isForceHidden.value = true
assertThat(latest).isFalse()
job.cancel()
}
@Test
fun isVisible_respondsToUpdates() =
testScope.runTest {
var latest: Boolean? = null
val job = underTest.isVisible.onEach { latest = it }.launchIn(this)
airplaneModeRepository.setIsAirplaneMode(false)
interactor.isForceHidden.value = false
assertThat(latest).isTrue()
airplaneModeRepository.setIsAirplaneMode(true)
assertThat(latest).isFalse()
airplaneModeRepository.setIsAirplaneMode(false)
assertThat(latest).isTrue()
interactor.isForceHidden.value = true
assertThat(latest).isFalse()
job.cancel()
}
@Test
fun iconId_correctLevel_notCutout() =
testScope.runTest {
@@ -361,13 +455,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
testScope.runTest {
// Create a new view model here so the constants are properly read
whenever(constants.shouldShowActivityConfig).thenReturn(false)
underTest =
MobileIconViewModel(
SUB_1_ID,
interactor,
constants,
testScope.backgroundScope,
)
createAndSetViewModel()
var inVisible: Boolean? = null
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
@@ -399,13 +487,7 @@ class MobileIconViewModelTest : SysuiTestCase() {
testScope.runTest {
// Create a new view model here so the constants are properly read
whenever(constants.shouldShowActivityConfig).thenReturn(true)
underTest =
MobileIconViewModel(
SUB_1_ID,
interactor,
constants,
testScope.backgroundScope,
)
createAndSetViewModel()
var inVisible: Boolean? = null
val inJob = underTest.activityInVisible.onEach { inVisible = it }.launchIn(this)
@@ -454,6 +536,16 @@ class MobileIconViewModelTest : SysuiTestCase() {
containerJob.cancel()
}
private fun createAndSetViewModel() {
underTest = MobileIconViewModel(
SUB_1_ID,
interactor,
airplaneModeInteractor,
constants,
testScope.backgroundScope,
)
}
companion object {
private const val SUB_1_ID = 1

View File

@@ -20,11 +20,14 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.statusbar.phone.StatusBarLocation
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.mobile.data.model.SubscriptionModel
import com.android.systemui.statusbar.pipeline.mobile.domain.interactor.FakeMobileIconsInteractor
import com.android.systemui.statusbar.pipeline.mobile.util.FakeMobileMappingsProxy
import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -46,6 +49,7 @@ class MobileIconsViewModelTest : SysuiTestCase() {
private lateinit var underTest: MobileIconsViewModel
private val interactor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
private lateinit var airplaneModeInteractor: AirplaneModeInteractor
@Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
@Mock private lateinit var logger: ConnectivityPipelineLogger
@Mock private lateinit var constants: ConnectivityConstants
@@ -57,6 +61,12 @@ class MobileIconsViewModelTest : SysuiTestCase() {
fun setUp() {
MockitoAnnotations.initMocks(this)
airplaneModeInteractor =
AirplaneModeInteractor(
FakeAirplaneModeRepository(),
FakeConnectivityRepository(),
)
val subscriptionIdsFlow =
interactor.filteredSubscriptions
.map { subs -> subs.map { it.subscriptionId } }
@@ -66,6 +76,7 @@ class MobileIconsViewModelTest : SysuiTestCase() {
MobileIconsViewModel(
subscriptionIdsFlow,
interactor,
airplaneModeInteractor,
logger,
constants,
testScope.backgroundScope,