summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/res/values/ids.xml3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt54
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/HomeWifiViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/KeyguardWifiViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/QsWifiViewModel.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt183
10 files changed, 287 insertions, 31 deletions
diff --git a/packages/SystemUI/res/values/ids.xml b/packages/SystemUI/res/values/ids.xml
index 808425435efa..f22e79722e78 100644
--- a/packages/SystemUI/res/values/ids.xml
+++ b/packages/SystemUI/res/values/ids.xml
@@ -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" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
index cf7283c6442e..1196211bd671 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusIconDisplayable.java
@@ -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;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
index c3a9b90c5a62..273be63eb8a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt
@@ -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
@@ -45,6 +50,19 @@ import kotlinx.coroutines.launch
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
+ }
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
index b874fb10fd1d..6c616ac7c3b8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiView.kt
@@ -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()
+ }
+
+ private fun initView(
+ slotName: String,
+ wifiViewModel: WifiViewModel,
+ location: StatusBarLocation,
+ ) {
+ slot = slotName
+ initDotView()
+ binding = WifiViewBinder.bind(this, wifiViewModel, location)
}
- /** Set the slot name for this view. */
- private fun setSlot(slotName: String) {
- this.slot = slotName
+ // 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)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/HomeWifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/HomeWifiViewModel.kt
index 0847e6214337..871b395d0996 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/HomeWifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/HomeWifiViewModel.kt
@@ -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>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/KeyguardWifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/KeyguardWifiViewModel.kt
index 3f7c8e13d7f7..be1f3f2194bc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/KeyguardWifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/KeyguardWifiViewModel.kt
@@ -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>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt
index d34ba88cde1a..7243acfbd56d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/LocationBasedWifiViewModel.kt
@@ -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>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/QsWifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/QsWifiViewModel.kt
index 8f6c26a6620f..d640d33eb316 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/QsWifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/QsWifiViewModel.kt
@@ -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>,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
index 13fd922720f6..465f5097235e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt
@@ -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,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
index cbb4b7e05176..a93b6b28e3b3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt
@@ -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"