[SB Refactor] Connect the old pipeline and new pipeline visibility
calculations together for wifi. The _new_ pipeline has the source of truth for whether the wifi icon *should* be visible. But, the _old_ view system has the source of truth for whether the wifi icon *can* be visible (i.e. if there's enough space for it). This CL hooks up those two systems together by having `WifiViewBinder#bind` return a `Binding` interface implementation, similar to `KeyguardButtomAreaViewBinder#bind`. This allows them to communicate with each other and correctly change the view's visibility. Bug: 238425913 Test: manual: Go into airplane mode and verify that the wifi icon disappears completely and there's no empty gap in the status bar. Test: manual: Go into a state where there's not enough room for the wifi icon and verify that just a tinted dot shows up. See demo video in b/238425913#comment30. Test: statusbar.pipeline tests Change-Id: I9d421a4afb503c9327578f777561a4d38bf2fd48
This commit is contained in:
@@ -131,6 +131,9 @@
|
||||
<!-- For StatusIconContainer to tag its icon views -->
|
||||
<item type="id" name="status_bar_view_state_tag" />
|
||||
|
||||
<!-- Status bar -->
|
||||
<item type="id" name="status_bar_dot" />
|
||||
|
||||
<!-- Default display cutout on the physical top of screen -->
|
||||
<item type="id" name="display_cutout" />
|
||||
<item type="id" name="display_cutout_left" />
|
||||
|
||||
@@ -38,7 +38,15 @@ public interface StatusIconDisplayable extends DarkReceiver {
|
||||
@StatusBarIconView.VisibleState
|
||||
int getVisibleState();
|
||||
|
||||
/**
|
||||
* Returns true if this icon should be visible if there's space, and false otherwise.
|
||||
*
|
||||
* Note that this doesn't necessarily mean it *will* be visible. It's possible that there are
|
||||
* more icons than space, in which case this icon might just show a dot or might be completely
|
||||
* hidden. {@link #getVisibleState} will return the icon's actual visible status.
|
||||
*/
|
||||
boolean isIconVisible();
|
||||
|
||||
default boolean isIconBlocked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -26,10 +26,15 @@ import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.common.ui.binder.IconViewBinder
|
||||
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||
import com.android.systemui.statusbar.StatusBarIconView
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
||||
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
|
||||
import kotlinx.coroutines.InternalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -44,6 +49,19 @@ import kotlinx.coroutines.launch
|
||||
@OptIn(InternalCoroutinesApi::class)
|
||||
object WifiViewBinder {
|
||||
|
||||
/**
|
||||
* Defines interface for an object that acts as the binding between the view and its view-model.
|
||||
*
|
||||
* Users of the [WifiViewBinder] class should use this to control the binder after it is bound.
|
||||
*/
|
||||
interface Binding {
|
||||
/** Returns true if the wifi icon should be visible and false otherwise. */
|
||||
fun getShouldIconBeVisible(): Boolean
|
||||
|
||||
/** Notifies that the visibility state has changed. */
|
||||
fun onVisibilityStateChanged(@StatusBarIconView.VisibleState state: Int)
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the view to the appropriate view-model based on the given location. The view will
|
||||
* continue to be updated following updates from the view-model.
|
||||
@@ -53,8 +71,8 @@ object WifiViewBinder {
|
||||
view: ViewGroup,
|
||||
wifiViewModel: WifiViewModel,
|
||||
location: StatusBarLocation,
|
||||
) {
|
||||
when (location) {
|
||||
): Binding {
|
||||
return when (location) {
|
||||
StatusBarLocation.HOME -> bind(view, wifiViewModel.home)
|
||||
StatusBarLocation.KEYGUARD -> bind(view, wifiViewModel.keyguard)
|
||||
StatusBarLocation.QS -> bind(view, wifiViewModel.qs)
|
||||
@@ -66,8 +84,10 @@ object WifiViewBinder {
|
||||
private fun bind(
|
||||
view: ViewGroup,
|
||||
viewModel: LocationBasedWifiViewModel,
|
||||
) {
|
||||
): Binding {
|
||||
val groupView = view.requireViewById<ViewGroup>(R.id.wifi_group)
|
||||
val iconView = view.requireViewById<ImageView>(R.id.wifi_signal)
|
||||
val dotView = view.requireViewById<StatusBarIconView>(R.id.status_bar_dot)
|
||||
val activityInView = view.requireViewById<ImageView>(R.id.wifi_in)
|
||||
val activityOutView = view.requireViewById<ImageView>(R.id.wifi_out)
|
||||
val activityContainerView = view.requireViewById<View>(R.id.inout_container)
|
||||
@@ -75,14 +95,21 @@ object WifiViewBinder {
|
||||
view.isVisible = true
|
||||
iconView.isVisible = true
|
||||
|
||||
// TODO(b/238425913): We should log this visibility state.
|
||||
@StatusBarIconView.VisibleState
|
||||
val visibilityState: MutableStateFlow<Int> = MutableStateFlow(STATE_HIDDEN)
|
||||
|
||||
view.repeatWhenAttached {
|
||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||
launch {
|
||||
viewModel.wifiIcon.distinctUntilChanged().collect { wifiIcon ->
|
||||
// TODO(b/238425913): Right now, if !isVisible, there's just an empty space
|
||||
// where the wifi icon would be. We need to pipe isVisible through to
|
||||
// [ModernStatusBarWifiView.isIconVisible], which is what actually makes
|
||||
// the view GONE.
|
||||
visibilityState.collect { visibilityState ->
|
||||
groupView.isVisible = visibilityState == STATE_ICON
|
||||
dotView.isVisible = visibilityState == STATE_DOT
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
viewModel.wifiIcon.collect { wifiIcon ->
|
||||
view.isVisible = wifiIcon != null
|
||||
wifiIcon?.let { IconViewBinder.bind(wifiIcon, iconView) }
|
||||
}
|
||||
@@ -94,6 +121,7 @@ object WifiViewBinder {
|
||||
iconView.imageTintList = tintList
|
||||
activityInView.imageTintList = tintList
|
||||
activityOutView.imageTintList = tintList
|
||||
dotView.setDecorColor(tint)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,5 +144,15 @@ object WifiViewBinder {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return object : Binding {
|
||||
override fun getShouldIconBeVisible(): Boolean {
|
||||
return viewModel.wifiIcon.value != null
|
||||
}
|
||||
|
||||
override fun onVisibilityStateChanged(@StatusBarIconView.VisibleState state: Int) {
|
||||
visibilityState.value = state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,13 @@ package com.android.systemui.statusbar.pipeline.wifi.ui.view
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.statusbar.BaseStatusBarWifiView
|
||||
import com.android.systemui.statusbar.StatusBarIconView
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
|
||||
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.binder.WifiViewBinder
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
|
||||
@@ -38,6 +40,17 @@ class ModernStatusBarWifiView(
|
||||
) : BaseStatusBarWifiView(context, attrs) {
|
||||
|
||||
private lateinit var slot: String
|
||||
private lateinit var binding: WifiViewBinder.Binding
|
||||
|
||||
@StatusBarIconView.VisibleState
|
||||
private var iconVisibleState: Int = STATE_HIDDEN
|
||||
set(value) {
|
||||
if (field == value) {
|
||||
return
|
||||
}
|
||||
field = value
|
||||
binding.onVisibilityStateChanged(value)
|
||||
}
|
||||
|
||||
override fun onDarkChanged(areas: ArrayList<Rect>?, darkIntensity: Float, tint: Int) {
|
||||
// TODO(b/238425913)
|
||||
@@ -54,23 +67,44 @@ class ModernStatusBarWifiView(
|
||||
}
|
||||
|
||||
override fun setVisibleState(@StatusBarIconView.VisibleState state: Int, animate: Boolean) {
|
||||
// TODO(b/238425913)
|
||||
iconVisibleState = state
|
||||
}
|
||||
|
||||
@StatusBarIconView.VisibleState
|
||||
override fun getVisibleState(): Int {
|
||||
// TODO(b/238425913)
|
||||
return STATE_ICON
|
||||
return iconVisibleState
|
||||
}
|
||||
|
||||
override fun isIconVisible(): Boolean {
|
||||
// TODO(b/238425913)
|
||||
return true
|
||||
return binding.getShouldIconBeVisible()
|
||||
}
|
||||
|
||||
/** Set the slot name for this view. */
|
||||
private fun setSlot(slotName: String) {
|
||||
this.slot = slotName
|
||||
private fun initView(
|
||||
slotName: String,
|
||||
wifiViewModel: WifiViewModel,
|
||||
location: StatusBarLocation,
|
||||
) {
|
||||
slot = slotName
|
||||
initDotView()
|
||||
binding = WifiViewBinder.bind(this, wifiViewModel, location)
|
||||
}
|
||||
|
||||
// Mostly duplicated from [com.android.systemui.statusbar.StatusBarWifiView].
|
||||
private fun initDotView() {
|
||||
// TODO(b/238425913): Could we just have this dot view be part of
|
||||
// R.layout.new_status_bar_wifi_group with a dot drawable so we don't need to inflate it
|
||||
// manually? Would that not work with animations?
|
||||
val dotView = StatusBarIconView(mContext, slot, null).also {
|
||||
it.id = R.id.status_bar_dot
|
||||
// Hard-code this view to always be in the DOT state so that whenever it's visible it
|
||||
// will show a dot
|
||||
it.visibleState = STATE_DOT
|
||||
}
|
||||
|
||||
val width = mContext.resources.getDimensionPixelSize(R.dimen.status_bar_icon_size)
|
||||
val lp = LayoutParams(width, width)
|
||||
lp.gravity = Gravity.CENTER_VERTICAL or Gravity.START
|
||||
addView(dotView, lp)
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -89,8 +123,7 @@ class ModernStatusBarWifiView(
|
||||
LayoutInflater.from(context).inflate(R.layout.new_status_bar_wifi_group, null)
|
||||
as ModernStatusBarWifiView
|
||||
).also {
|
||||
it.setSlot(slot)
|
||||
WifiViewBinder.bind(it, wifiViewModel, location)
|
||||
it.initView(slot, wifiViewModel, location)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.graphics.Color
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/**
|
||||
* A view model for the wifi icon shown on the "home" page (aka, when the device is unlocked and not
|
||||
@@ -27,7 +28,7 @@ import kotlinx.coroutines.flow.Flow
|
||||
*/
|
||||
class HomeWifiViewModel(
|
||||
statusBarPipelineFlags: StatusBarPipelineFlags,
|
||||
wifiIcon: Flow<Icon?>,
|
||||
wifiIcon: StateFlow<Icon?>,
|
||||
isActivityInViewVisible: Flow<Boolean>,
|
||||
isActivityOutViewVisible: Flow<Boolean>,
|
||||
isActivityContainerVisible: Flow<Boolean>,
|
||||
|
||||
@@ -20,11 +20,12 @@ import android.graphics.Color
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/** A view model for the wifi icon shown on keyguard (lockscreen). */
|
||||
class KeyguardWifiViewModel(
|
||||
statusBarPipelineFlags: StatusBarPipelineFlags,
|
||||
wifiIcon: Flow<Icon?>,
|
||||
wifiIcon: StateFlow<Icon?>,
|
||||
isActivityInViewVisible: Flow<Boolean>,
|
||||
isActivityOutViewVisible: Flow<Boolean>,
|
||||
isActivityContainerVisible: Flow<Boolean>,
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.graphics.Color
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
/**
|
||||
@@ -33,7 +34,7 @@ abstract class LocationBasedWifiViewModel(
|
||||
debugTint: Int,
|
||||
|
||||
/** The wifi icon that should be displayed. Null if we shouldn't display any icon. */
|
||||
val wifiIcon: Flow<Icon?>,
|
||||
val wifiIcon: StateFlow<Icon?>,
|
||||
|
||||
/** True if the activity in view should be visible. */
|
||||
val isActivityInViewVisible: Flow<Boolean>,
|
||||
|
||||
@@ -20,11 +20,12 @@ import android.graphics.Color
|
||||
import com.android.systemui.common.shared.model.Icon
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
|
||||
/** A view model for the wifi icon shown in quick settings (when the shade is pulled down). */
|
||||
class QsWifiViewModel(
|
||||
statusBarPipelineFlags: StatusBarPipelineFlags,
|
||||
wifiIcon: Flow<Icon?>,
|
||||
wifiIcon: StateFlow<Icon?>,
|
||||
isActivityInViewVisible: Flow<Boolean>,
|
||||
isActivityOutViewVisible: Flow<Boolean>,
|
||||
isActivityContainerVisible: Flow<Boolean>,
|
||||
|
||||
@@ -41,6 +41,7 @@ import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
@@ -120,7 +121,7 @@ constructor(
|
||||
.stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = null)
|
||||
|
||||
/** The wifi icon that should be displayed. Null if we shouldn't display any icon. */
|
||||
private val wifiIcon: Flow<Icon?> =
|
||||
private val wifiIcon: StateFlow<Icon?> =
|
||||
combine(
|
||||
interactor.isEnabled,
|
||||
interactor.isForceHidden,
|
||||
|
||||
@@ -16,39 +16,208 @@
|
||||
|
||||
package com.android.systemui.statusbar.pipeline.wifi.ui.view
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import android.testing.ViewUtils
|
||||
import android.view.View
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.lifecycle.InstantTaskExecutorRule
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN
|
||||
import com.android.systemui.statusbar.StatusBarIconView.STATE_ICON
|
||||
import com.android.systemui.statusbar.phone.StatusBarLocation
|
||||
import com.android.systemui.util.Assert
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags
|
||||
import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger
|
||||
import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository
|
||||
import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor
|
||||
import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants
|
||||
import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.JUnit4
|
||||
import org.mockito.Mock
|
||||
import org.mockito.MockitoAnnotations
|
||||
|
||||
@SmallTest
|
||||
@RunWith(JUnit4::class)
|
||||
@RunWithLooper
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper(setAsMainLooper = true)
|
||||
class ModernStatusBarWifiViewTest : SysuiTestCase() {
|
||||
|
||||
private lateinit var testableLooper: TestableLooper
|
||||
|
||||
@Mock
|
||||
private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags
|
||||
@Mock
|
||||
private lateinit var logger: ConnectivityPipelineLogger
|
||||
@Mock
|
||||
private lateinit var constants: WifiConstants
|
||||
private lateinit var connectivityRepository: FakeConnectivityRepository
|
||||
private lateinit var wifiRepository: FakeWifiRepository
|
||||
private lateinit var interactor: WifiInteractor
|
||||
private lateinit var viewModel: WifiViewModel
|
||||
private lateinit var scope: CoroutineScope
|
||||
|
||||
@JvmField @Rule
|
||||
val instantTaskExecutor = InstantTaskExecutorRule()
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
Assert.setTestThread(Thread.currentThread())
|
||||
MockitoAnnotations.initMocks(this)
|
||||
testableLooper = TestableLooper.get(this)
|
||||
|
||||
connectivityRepository = FakeConnectivityRepository()
|
||||
wifiRepository = FakeWifiRepository()
|
||||
wifiRepository.setIsWifiEnabled(true)
|
||||
interactor = WifiInteractor(connectivityRepository, wifiRepository)
|
||||
scope = CoroutineScope(Dispatchers.Unconfined)
|
||||
viewModel = WifiViewModel(
|
||||
constants, context, logger, interactor, scope, statusBarPipelineFlags
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun constructAndBind_hasCorrectSlot() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, "slotName", mock(), StatusBarLocation.HOME
|
||||
context, "slotName", viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
assertThat(view.slot).isEqualTo("slotName")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleState_icon_returnsIcon() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
view.setVisibleState(STATE_ICON, /* animate= */ false)
|
||||
|
||||
assertThat(view.visibleState).isEqualTo(STATE_ICON)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleState_dot_returnsDot() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
view.setVisibleState(STATE_DOT, /* animate= */ false)
|
||||
|
||||
assertThat(view.visibleState).isEqualTo(STATE_DOT)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getVisibleState_hidden_returnsHidden() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
view.setVisibleState(STATE_HIDDEN, /* animate= */ false)
|
||||
|
||||
assertThat(view.visibleState).isEqualTo(STATE_HIDDEN)
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
@Test
|
||||
fun setVisibleState_icon_iconShownDotHidden() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
view.setVisibleState(STATE_ICON, /* animate= */ false)
|
||||
|
||||
ViewUtils.attachView(view)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
assertThat(view.getIconGroupView().visibility).isEqualTo(View.VISIBLE)
|
||||
assertThat(view.getDotView().visibility).isEqualTo(View.GONE)
|
||||
|
||||
ViewUtils.detachView(view)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setVisibleState_dot_iconHiddenDotShown() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
view.setVisibleState(STATE_DOT, /* animate= */ false)
|
||||
|
||||
ViewUtils.attachView(view)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
assertThat(view.getIconGroupView().visibility).isEqualTo(View.GONE)
|
||||
assertThat(view.getDotView().visibility).isEqualTo(View.VISIBLE)
|
||||
|
||||
ViewUtils.detachView(view)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun setVisibleState_hidden_iconAndDotHidden() {
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
view.setVisibleState(STATE_HIDDEN, /* animate= */ false)
|
||||
|
||||
ViewUtils.attachView(view)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
assertThat(view.getIconGroupView().visibility).isEqualTo(View.GONE)
|
||||
assertThat(view.getDotView().visibility).isEqualTo(View.GONE)
|
||||
|
||||
ViewUtils.detachView(view)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isIconVisible_notEnabled_outputsFalse() {
|
||||
wifiRepository.setIsWifiEnabled(false)
|
||||
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
ViewUtils.attachView(view)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
assertThat(view.isIconVisible).isFalse()
|
||||
|
||||
ViewUtils.detachView(view)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun isIconVisible_enabled_outputsTrue() {
|
||||
wifiRepository.setIsWifiEnabled(true)
|
||||
|
||||
val view = ModernStatusBarWifiView.constructAndBind(
|
||||
context, SLOT_NAME, viewModel, StatusBarLocation.HOME
|
||||
)
|
||||
|
||||
ViewUtils.attachView(view)
|
||||
testableLooper.processAllMessages()
|
||||
|
||||
assertThat(view.isIconVisible).isTrue()
|
||||
|
||||
ViewUtils.detachView(view)
|
||||
}
|
||||
|
||||
private fun View.getIconGroupView(): View {
|
||||
return this.requireViewById(R.id.wifi_group)
|
||||
}
|
||||
|
||||
private fun View.getDotView(): View {
|
||||
return this.requireViewById(R.id.status_bar_dot)
|
||||
}
|
||||
}
|
||||
|
||||
private const val SLOT_NAME = "TestSlotName"
|
||||
|
||||
Reference in New Issue
Block a user