Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt +11 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.Context import android.graphics.drawable.Drawable import android.service.quicksettings.Tile import com.android.settingslib.graph.SignalDrawable import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription import com.android.systemui.common.shared.model.Text import com.android.systemui.common.shared.model.Text.Companion.loadText import com.android.systemui.plugins.qs.QSTile Loading @@ -31,6 +33,8 @@ sealed interface InternetTileModel { val secondaryLabel: Text? val iconId: Int? val icon: QSTile.Icon? val stateDescription: ContentDescription? val contentDescription: ContentDescription? fun applyTo(state: QSTile.BooleanState, context: Context) { if (secondaryLabel != null) { Loading @@ -39,6 +43,9 @@ sealed interface InternetTileModel { state.secondaryLabel = secondaryTitle } state.stateDescription = stateDescription.loadContentDescription(context) state.contentDescription = contentDescription.loadContentDescription(context) // To support both SignalDrawable and other icons, give priority to icons over IDs if (icon != null) { state.icon = icon Loading @@ -59,6 +66,8 @@ sealed interface InternetTileModel { override val secondaryLabel: Text? = null, override val iconId: Int? = null, override val icon: QSTile.Icon? = null, override val stateDescription: ContentDescription? = null, override val contentDescription: ContentDescription? = null, ) : InternetTileModel data class Inactive( Loading @@ -66,6 +75,8 @@ sealed interface InternetTileModel { override val secondaryLabel: Text? = null, override val iconId: Int? = null, override val icon: QSTile.Icon? = null, override val stateDescription: ContentDescription? = null, override val contentDescription: ContentDescription? = null, ) : InternetTileModel } Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt +32 −10 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel import android.content.Context import com.android.systemui.R import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Text import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application Loading Loading @@ -61,16 +62,21 @@ constructor( private val context: Context, @Application scope: CoroutineScope, ) { private val internetLabel: String = context.getString(R.string.quick_settings_internet_label) // Three symmetrical Flows that can be switched upon based on the value of // [DefaultConnectionModel] private val wifiIconFlow: Flow<InternetTileModel> = wifiInteractor.wifiNetwork.flatMapLatest { val wifiIcon = WifiIcon.fromModel(it, context, showHotspotInfo = true) if (it is WifiNetworkModel.Active && wifiIcon is WifiIcon.Visible) { val secondary = removeDoubleQuotes(it.ssid) flowOf( InternetTileModel.Active( secondaryTitle = removeDoubleQuotes(it.ssid), icon = ResourceIcon.get(wifiIcon.icon.res) secondaryTitle = secondary, icon = ResourceIcon.get(wifiIcon.icon.res), stateDescription = wifiIcon.contentDescription, contentDescription = ContentDescription.Loaded("$internetLabel,$secondary"), ) ) } else { Loading Loading @@ -109,10 +115,13 @@ constructor( it.signalLevelIcon, mobileDataContentName, ) { networkNameModel, signalIcon, dataContentDescription -> val secondary = mobileDataContentConcat(networkNameModel.name, dataContentDescription) InternetTileModel.Active( secondaryTitle = mobileDataContentConcat(networkNameModel.name, dataContentDescription), secondaryTitle = secondary, icon = SignalIcon(signalIcon.toSignalDrawableState()), stateDescription = ContentDescription.Loaded(secondary), contentDescription = ContentDescription.Loaded(internetLabel), ) } } Loading Loading @@ -148,10 +157,13 @@ constructor( if (it == null) { notConnectedFlow } else { val secondary = it.contentDescription.toString() flowOf( InternetTileModel.Active( secondaryTitle = it.contentDescription.toString(), iconId = it.res secondaryTitle = secondary, iconId = it.res, stateDescription = null, contentDescription = ContentDescription.Loaded(secondary), ) ) } Loading @@ -164,16 +176,23 @@ constructor( ) { networksAvailable, isAirplaneMode -> when { isAirplaneMode -> { val secondary = context.getString(R.string.status_bar_airplane) InternetTileModel.Inactive( secondaryTitle = context.getString(R.string.status_bar_airplane), icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable) secondaryTitle = secondary, icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable), stateDescription = null, contentDescription = ContentDescription.Loaded(secondary), ) } networksAvailable -> { val secondary = context.getString(R.string.quick_settings_networks_available) InternetTileModel.Inactive( secondaryTitle = context.getString(R.string.quick_settings_networks_available), secondaryTitle = secondary, iconId = R.drawable.ic_qs_no_internet_available, stateDescription = null, contentDescription = ContentDescription.Loaded("$internetLabel,$secondary") ) } else -> { Loading Loading @@ -206,6 +225,9 @@ constructor( InternetTileModel.Inactive( secondaryLabel = Text.Resource(R.string.quick_settings_networks_unavailable), iconId = R.drawable.ic_qs_no_internet_unavailable, stateDescription = null, contentDescription = ContentDescription.Resource(R.string.quick_settings_networks_unavailable), ) private fun removeDoubleQuotes(string: String?): String? { Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt +26 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription import com.android.systemui.common.shared.model.Text import com.android.systemui.coroutines.collectLastValue import com.android.systemui.log.table.TableLogBuffer Loading @@ -42,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepo import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat Loading Loading @@ -72,6 +74,8 @@ class InternetTileViewModelTest : SysuiTestCase() { private val mobileConnectionRepository = FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer) private val internet = context.getString(R.string.quick_settings_internet_label) @Before fun setUp() { mobileConnectionRepository.apply { Loading Loading @@ -139,6 +143,9 @@ class InternetTileViewModelTest : SysuiTestCase() { level = 4, ssid = "test ssid", ) val wifiIcon = WifiIcon.fromModel(model = networkModel, context = context, showHotspotInfo = false) as WifiIcon.Visible connectivityRepository.setWifiConnected() wifiRepository.setIsWifiDefault(true) Loading @@ -149,6 +156,10 @@ class InternetTileViewModelTest : SysuiTestCase() { assertThat(latest?.icon) .isEqualTo(ResourceIcon.get(WifiIcons.WIFI_NO_INTERNET_ICONS[4])) assertThat(latest?.iconId).isNull() assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo("$internet,test ssid") val expectedSd = wifiIcon.contentDescription assertThat(latest?.stateDescription).isEqualTo(expectedSd) } @Test Loading Loading @@ -281,6 +292,11 @@ class InternetTileViewModelTest : SysuiTestCase() { .isEqualTo(context.getString(R.string.quick_settings_networks_available)) assertThat(latest?.icon).isNull() assertThat(latest?.iconId).isEqualTo(R.drawable.ic_qs_no_internet_available) assertThat(latest?.stateDescription).isNull() val expectedCd = "$internet,${context.getString(R.string.quick_settings_networks_available)}" assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(expectedCd) } @Test Loading @@ -300,6 +316,10 @@ class InternetTileViewModelTest : SysuiTestCase() { assertThat(latest?.secondaryLabel).isNull() assertThat(latest?.icon).isInstanceOf(SignalIcon::class.java) assertThat(latest?.iconId).isNull() assertThat(latest?.stateDescription.loadContentDescription(context)) .isEqualTo(latest?.secondaryTitle) assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(internet) } @Test Loading @@ -315,6 +335,9 @@ class InternetTileViewModelTest : SysuiTestCase() { .isEqualTo(ethernetIcon!!.contentDescription.toString()) assertThat(latest?.iconId).isEqualTo(R.drawable.stat_sys_ethernet_fully) assertThat(latest?.icon).isNull() assertThat(latest?.stateDescription).isNull() assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(latest?.secondaryTitle) } @Test Loading @@ -330,6 +353,9 @@ class InternetTileViewModelTest : SysuiTestCase() { .isEqualTo(ethernetIcon!!.contentDescription.toString()) assertThat(latest?.iconId).isEqualTo(R.drawable.stat_sys_ethernet) assertThat(latest?.icon).isNull() assertThat(latest?.stateDescription).isNull() assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(latest?.secondaryTitle) } private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) { Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/model/InternetTileModel.kt +11 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,8 @@ import android.content.Context import android.graphics.drawable.Drawable import android.service.quicksettings.Tile import com.android.settingslib.graph.SignalDrawable import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription import com.android.systemui.common.shared.model.Text import com.android.systemui.common.shared.model.Text.Companion.loadText import com.android.systemui.plugins.qs.QSTile Loading @@ -31,6 +33,8 @@ sealed interface InternetTileModel { val secondaryLabel: Text? val iconId: Int? val icon: QSTile.Icon? val stateDescription: ContentDescription? val contentDescription: ContentDescription? fun applyTo(state: QSTile.BooleanState, context: Context) { if (secondaryLabel != null) { Loading @@ -39,6 +43,9 @@ sealed interface InternetTileModel { state.secondaryLabel = secondaryTitle } state.stateDescription = stateDescription.loadContentDescription(context) state.contentDescription = contentDescription.loadContentDescription(context) // To support both SignalDrawable and other icons, give priority to icons over IDs if (icon != null) { state.icon = icon Loading @@ -59,6 +66,8 @@ sealed interface InternetTileModel { override val secondaryLabel: Text? = null, override val iconId: Int? = null, override val icon: QSTile.Icon? = null, override val stateDescription: ContentDescription? = null, override val contentDescription: ContentDescription? = null, ) : InternetTileModel data class Inactive( Loading @@ -66,6 +75,8 @@ sealed interface InternetTileModel { override val secondaryLabel: Text? = null, override val iconId: Int? = null, override val icon: QSTile.Icon? = null, override val stateDescription: ContentDescription? = null, override val contentDescription: ContentDescription? = null, ) : InternetTileModel } Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModel.kt +32 −10 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel import android.content.Context import com.android.systemui.R import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Text import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application Loading Loading @@ -61,16 +62,21 @@ constructor( private val context: Context, @Application scope: CoroutineScope, ) { private val internetLabel: String = context.getString(R.string.quick_settings_internet_label) // Three symmetrical Flows that can be switched upon based on the value of // [DefaultConnectionModel] private val wifiIconFlow: Flow<InternetTileModel> = wifiInteractor.wifiNetwork.flatMapLatest { val wifiIcon = WifiIcon.fromModel(it, context, showHotspotInfo = true) if (it is WifiNetworkModel.Active && wifiIcon is WifiIcon.Visible) { val secondary = removeDoubleQuotes(it.ssid) flowOf( InternetTileModel.Active( secondaryTitle = removeDoubleQuotes(it.ssid), icon = ResourceIcon.get(wifiIcon.icon.res) secondaryTitle = secondary, icon = ResourceIcon.get(wifiIcon.icon.res), stateDescription = wifiIcon.contentDescription, contentDescription = ContentDescription.Loaded("$internetLabel,$secondary"), ) ) } else { Loading Loading @@ -109,10 +115,13 @@ constructor( it.signalLevelIcon, mobileDataContentName, ) { networkNameModel, signalIcon, dataContentDescription -> val secondary = mobileDataContentConcat(networkNameModel.name, dataContentDescription) InternetTileModel.Active( secondaryTitle = mobileDataContentConcat(networkNameModel.name, dataContentDescription), secondaryTitle = secondary, icon = SignalIcon(signalIcon.toSignalDrawableState()), stateDescription = ContentDescription.Loaded(secondary), contentDescription = ContentDescription.Loaded(internetLabel), ) } } Loading Loading @@ -148,10 +157,13 @@ constructor( if (it == null) { notConnectedFlow } else { val secondary = it.contentDescription.toString() flowOf( InternetTileModel.Active( secondaryTitle = it.contentDescription.toString(), iconId = it.res secondaryTitle = secondary, iconId = it.res, stateDescription = null, contentDescription = ContentDescription.Loaded(secondary), ) ) } Loading @@ -164,16 +176,23 @@ constructor( ) { networksAvailable, isAirplaneMode -> when { isAirplaneMode -> { val secondary = context.getString(R.string.status_bar_airplane) InternetTileModel.Inactive( secondaryTitle = context.getString(R.string.status_bar_airplane), icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable) secondaryTitle = secondary, icon = ResourceIcon.get(R.drawable.ic_qs_no_internet_unavailable), stateDescription = null, contentDescription = ContentDescription.Loaded(secondary), ) } networksAvailable -> { val secondary = context.getString(R.string.quick_settings_networks_available) InternetTileModel.Inactive( secondaryTitle = context.getString(R.string.quick_settings_networks_available), secondaryTitle = secondary, iconId = R.drawable.ic_qs_no_internet_available, stateDescription = null, contentDescription = ContentDescription.Loaded("$internetLabel,$secondary") ) } else -> { Loading Loading @@ -206,6 +225,9 @@ constructor( InternetTileModel.Inactive( secondaryLabel = Text.Resource(R.string.quick_settings_networks_unavailable), iconId = R.drawable.ic_qs_no_internet_unavailable, stateDescription = null, contentDescription = ContentDescription.Resource(R.string.quick_settings_networks_unavailable), ) private fun removeDoubleQuotes(string: String?): String? { Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ui/viewmodel/InternetTileViewModelTest.kt +26 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.pipeline.shared.ui.viewmodel import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.ContentDescription.Companion.loadContentDescription import com.android.systemui.common.shared.model.Text import com.android.systemui.coroutines.collectLastValue import com.android.systemui.log.table.TableLogBuffer Loading @@ -42,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepo import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiScanEntry import com.android.systemui.statusbar.pipeline.wifi.ui.model.WifiIcon import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.mock import com.google.common.truth.Truth.assertThat Loading Loading @@ -72,6 +74,8 @@ class InternetTileViewModelTest : SysuiTestCase() { private val mobileConnectionRepository = FakeMobileConnectionRepository(SUB_1_ID, tableLogBuffer) private val internet = context.getString(R.string.quick_settings_internet_label) @Before fun setUp() { mobileConnectionRepository.apply { Loading Loading @@ -139,6 +143,9 @@ class InternetTileViewModelTest : SysuiTestCase() { level = 4, ssid = "test ssid", ) val wifiIcon = WifiIcon.fromModel(model = networkModel, context = context, showHotspotInfo = false) as WifiIcon.Visible connectivityRepository.setWifiConnected() wifiRepository.setIsWifiDefault(true) Loading @@ -149,6 +156,10 @@ class InternetTileViewModelTest : SysuiTestCase() { assertThat(latest?.icon) .isEqualTo(ResourceIcon.get(WifiIcons.WIFI_NO_INTERNET_ICONS[4])) assertThat(latest?.iconId).isNull() assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo("$internet,test ssid") val expectedSd = wifiIcon.contentDescription assertThat(latest?.stateDescription).isEqualTo(expectedSd) } @Test Loading Loading @@ -281,6 +292,11 @@ class InternetTileViewModelTest : SysuiTestCase() { .isEqualTo(context.getString(R.string.quick_settings_networks_available)) assertThat(latest?.icon).isNull() assertThat(latest?.iconId).isEqualTo(R.drawable.ic_qs_no_internet_available) assertThat(latest?.stateDescription).isNull() val expectedCd = "$internet,${context.getString(R.string.quick_settings_networks_available)}" assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(expectedCd) } @Test Loading @@ -300,6 +316,10 @@ class InternetTileViewModelTest : SysuiTestCase() { assertThat(latest?.secondaryLabel).isNull() assertThat(latest?.icon).isInstanceOf(SignalIcon::class.java) assertThat(latest?.iconId).isNull() assertThat(latest?.stateDescription.loadContentDescription(context)) .isEqualTo(latest?.secondaryTitle) assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(internet) } @Test Loading @@ -315,6 +335,9 @@ class InternetTileViewModelTest : SysuiTestCase() { .isEqualTo(ethernetIcon!!.contentDescription.toString()) assertThat(latest?.iconId).isEqualTo(R.drawable.stat_sys_ethernet_fully) assertThat(latest?.icon).isNull() assertThat(latest?.stateDescription).isNull() assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(latest?.secondaryTitle) } @Test Loading @@ -330,6 +353,9 @@ class InternetTileViewModelTest : SysuiTestCase() { .isEqualTo(ethernetIcon!!.contentDescription.toString()) assertThat(latest?.iconId).isEqualTo(R.drawable.stat_sys_ethernet) assertThat(latest?.icon).isNull() assertThat(latest?.stateDescription).isNull() assertThat(latest?.contentDescription.loadContentDescription(context)) .isEqualTo(latest?.secondaryTitle) } private fun setWifiNetworkWithHotspot(hotspot: WifiNetworkModel.HotspotDeviceType) { Loading