Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2dc080cb authored by Caitlin Shkuratov's avatar Caitlin Shkuratov
Browse files

[SB Refactor] Only show wifi icon if (1) the network is active and

validated; or (2) we're configured to always show it when enabled.

This matches part of the logic in
WifiSignalController#notifyListenersForNonCarrierWifi.wifiVisible.

Test: manual: With alwaysShow config off, verify that the wifi icon only
appears when we're fully connected to a network
Test: manual: With alwaysShow config on, verify that the wifi icon
always appears (unless wifi is disabled)
Test: statusbar.pipeline tests
Bug: 238425913

Change-Id: I723cfc0435265699f98b5b1adeb4cb9bbfaf2929
parent 022a2982
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -41,9 +41,14 @@ class WifiConstants @Inject constructor(
    /** True if we should show the activityIn/activityOut icons and false otherwise. */
    val shouldShowActivityConfig = context.resources.getBoolean(R.bool.config_showActivity)

    /** True if we should always show the wifi icon when wifi is enabled and false otherwise. */
    val alwaysShowIconIfEnabled =
        context.resources.getBoolean(R.bool.config_showWifiIndicatorWhenEnabled)

    override fun dump(pw: PrintWriter, args: Array<out String>) {
        pw.apply {
            println("shouldShowActivityConfig=$shouldShowActivityConfig")
            println("alwaysShowIconIfEnabled=$alwaysShowIconIfEnabled")
        }
    }
}
+53 −51
Original line number Diff line number Diff line
@@ -72,43 +72,42 @@ constructor(
    @Application private val scope: CoroutineScope,
    statusBarPipelineFlags: StatusBarPipelineFlags,
) {
    /** The drawable resource ID to use for the wifi icon. Null if we shouldn't display any icon. */
    /**
     * Returns the drawable resource ID to use for the wifi icon based on the given network.
     * Null if we can't compute the icon.
     */
    @DrawableRes
    private val iconResId: Flow<Int?> =
        interactor.wifiNetwork
            .map {
                when (it) {
    private fun WifiNetworkModel.iconResId(): Int? {
        return when (this) {
            is WifiNetworkModel.CarrierMerged -> null
            is WifiNetworkModel.Inactive -> WIFI_NO_NETWORK
            is WifiNetworkModel.Active ->
                when {
                            it.level == null -> null
                            it.isValidated -> WIFI_FULL_ICONS[it.level]
                            else -> WIFI_NO_INTERNET_ICONS[it.level]
                    this.level == null -> null
                    this.isValidated -> WIFI_FULL_ICONS[this.level]
                    else -> WIFI_NO_INTERNET_ICONS[this.level]
                }
        }
    }
            .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = null)

    /** The content description for the wifi icon. */
    private val contentDescription: Flow<ContentDescription?> =
        interactor.wifiNetwork
            .map {
                when (it) {
    /**
     * Returns the content description for the wifi icon based on the given network.
     * Null if we can't compute the content description.
     */
    private fun WifiNetworkModel.contentDescription(): ContentDescription? {
        return when (this) {
            is WifiNetworkModel.CarrierMerged -> null
            is WifiNetworkModel.Inactive ->
                ContentDescription.Loaded(
                            "${context.getString(WIFI_NO_CONNECTION)}," +
                                context.getString(NO_INTERNET)
                    "${context.getString(WIFI_NO_CONNECTION)},${context.getString(NO_INTERNET)}"
                )
            is WifiNetworkModel.Active ->
                        when (it.level) {
                when (this.level) {
                    null -> null
                    else -> {
                                val levelDesc =
                                    context.getString(WIFI_CONNECTION_STRENGTH[it.level])
                        val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[this.level])
                        when {
                                    it.isValidated -> ContentDescription.Loaded(levelDesc)
                            this.isValidated -> ContentDescription.Loaded(levelDesc)
                            else ->
                                ContentDescription.Loaded(
                                    "$levelDesc,${context.getString(NO_INTERNET)}"
@@ -118,22 +117,25 @@ 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: StateFlow<Icon?> =
        combine(
            interactor.isEnabled,
            interactor.isForceHidden,
            iconResId,
            contentDescription,
        ) { isEnabled, isForceHidden, iconResId, contentDescription ->
            when {
                !isEnabled ||
                    isForceHidden ||
                    iconResId == null ||
                    iconResId <= 0 -> null
                else -> Icon.Resource(iconResId, contentDescription)
            interactor.wifiNetwork,
        ) { isEnabled, isForceHidden, wifiNetwork ->
            if (!isEnabled || isForceHidden || wifiNetwork is WifiNetworkModel.CarrierMerged) {
                return@combine null
            }

            val iconResId = wifiNetwork.iconResId() ?: return@combine null
            val icon = Icon.Resource(iconResId, wifiNetwork.contentDescription())

            return@combine when {
                constants.alwaysShowIconIfEnabled -> icon
                wifiNetwork is WifiNetworkModel.Active && wifiNetwork.isValidated -> icon
                else -> null
            }
        }
        .stateIn(scope, started = SharingStarted.WhileSubscribed(), initialValue = null)
+8 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.systemui.statusbar.phone.StatusBarLocation
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.model.WifiNetworkModel
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
@@ -182,6 +183,9 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() {
    @Test
    fun isIconVisible_notEnabled_outputsFalse() {
        wifiRepository.setIsWifiEnabled(false)
        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
        )

        val view = ModernStatusBarWifiView.constructAndBind(
            context, SLOT_NAME, viewModel, StatusBarLocation.HOME
@@ -198,6 +202,9 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() {
    @Test
    fun isIconVisible_enabled_outputsTrue() {
        wifiRepository.setIsWifiEnabled(true)
        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
        )

        val view = ModernStatusBarWifiView.constructAndBind(
            context, SLOT_NAME, viewModel, StatusBarLocation.HOME
@@ -221,3 +228,4 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() {
}

private const val SLOT_NAME = "TestSlotName"
private const val NETWORK_ID = 200
+67 −3
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import org.mockito.Mock
import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations

@Suppress("EXPERIMENTAL_IS_NOT_ENABLED")
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
class WifiViewModelTest : SysuiTestCase() {
@@ -137,7 +138,9 @@ class WifiViewModelTest : SysuiTestCase() {
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = 2))
        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(NETWORK_ID, isValidated = true, level = 2)
        )
        yield()

        assertThat(latest).isInstanceOf(Icon.Resource::class.java)
@@ -146,7 +149,31 @@ class WifiViewModelTest : SysuiTestCase() {
    }

    @Test
    fun wifiIcon_inactiveNetwork_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) {
    fun wifiIcon_inactiveNetwork_alwaysShowFalse_outputsNull() = runBlocking(IMMEDIATE) {
        whenever(constants.alwaysShowIconIfEnabled).thenReturn(false)
        createAndSetViewModel()

        // Start as non-null so we can verify we got the update
        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive)
        yield()

        assertThat(latest).isNull()

        job.cancel()
    }

    @Test
    fun wifiIcon_inactiveNetwork_alwaysShowTrue_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) {
        whenever(constants.alwaysShowIconIfEnabled).thenReturn(true)
        createAndSetViewModel()

        var latest: Icon? = null
        val job = underTest
            .home
@@ -170,6 +197,10 @@ class WifiViewModelTest : SysuiTestCase() {

    @Test
    fun wifiIcon_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) {
        // Even when we should always show the icon
        whenever(constants.alwaysShowIconIfEnabled).thenReturn(true)
        createAndSetViewModel()

        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
@@ -177,9 +208,11 @@ class WifiViewModelTest : SysuiTestCase() {
            .onEach { latest = it }
            .launchIn(this)

        // WHEN we have a carrier merged network
        wifiRepository.setWifiNetwork(WifiNetworkModel.CarrierMerged)
        yield()

        // THEN we override the alwaysShow boolean and still don't show the icon
        assertThat(latest).isNull()

        job.cancel()
@@ -187,6 +220,10 @@ class WifiViewModelTest : SysuiTestCase() {

    @Test
    fun wifiIcon_isActiveNullLevel_outputsNull() = runBlocking(IMMEDIATE) {
        // Even when we should always show the icon
        whenever(constants.alwaysShowIconIfEnabled).thenReturn(true)
        createAndSetViewModel()

        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
@@ -194,9 +231,11 @@ class WifiViewModelTest : SysuiTestCase() {
            .onEach { latest = it }
            .launchIn(this)

        // WHEN we have a null level
        wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = null))
        yield()

        // THEN we override the alwaysShow boolean and still don't show the icon
        assertThat(latest).isNull()

        job.cancel()
@@ -233,7 +272,32 @@ class WifiViewModelTest : SysuiTestCase() {
    }

    @Test
    fun wifiIcon_isActiveAndNotValidated_level4_outputsEmpty4Icon() = runBlocking(IMMEDIATE) {
    fun wifiIcon_isActiveAndNotValidated_alwaysShowFalse_outputsNull() = runBlocking(IMMEDIATE) {
        whenever(constants.alwaysShowIconIfEnabled).thenReturn(false)
        createAndSetViewModel()

        var latest: Icon? = Icon.Resource(0, null)
        val job = underTest
            .home
            .wifiIcon
            .onEach { latest = it }
            .launchIn(this)

        wifiRepository.setWifiNetwork(
            WifiNetworkModel.Active(NETWORK_ID, isValidated = false, level = 4,)
        )
        yield()

        assertThat(latest).isNull()

        job.cancel()
    }

    @Test
    fun wifiIcon_isActiveAndNotValidated_alwaysShowTrue_outputsIcon() = runBlocking(IMMEDIATE) {
        whenever(constants.alwaysShowIconIfEnabled).thenReturn(true)
        createAndSetViewModel()

        var latest: Icon? = null
        val job = underTest
            .home