[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:
@@ -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
|
||||
|
||||
@@ -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),
|
||||
)
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user