Loading packages/SettingsLib/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1660,6 +1660,8 @@ <string name="accessibility_phone_two_bars">Phone two bars.</string> <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_three_bars">Phone three bars.</string> <!-- Content description of the phone signal when it is four bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_four_bars">Phone four bars.</string> <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_signal_full">Phone signal full.</string> Loading packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java +53 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,59 @@ public class AccessibilityContentDescriptions { R.string.accessibility_phone_signal_full }; /** * @param level int in range [0-4] that describes the signal level * @return the appropriate content description for that signal strength, or 0 if the param is * invalid */ public static int getDescriptionForLevel(int level) { if (level > 4 || level < 0) { return 0; } return PHONE_SIGNAL_STRENGTH[level]; } public static final int[] PHONE_SIGNAL_STRENGTH_INFLATED = { PHONE_SIGNAL_STRENGTH_NONE, R.string.accessibility_phone_one_bar, R.string.accessibility_phone_two_bars, R.string.accessibility_phone_three_bars, R.string.accessibility_phone_four_bars, R.string.accessibility_phone_signal_full }; /** * @param level int in range [0-5] that describes the inflated signal level * @return the appropriate content description for that signal strength, or 0 if the param is * invalid */ public static int getDescriptionForInflatedLevel(int level) { if (level > 5 || level < 0) { return 0; } return PHONE_SIGNAL_STRENGTH_INFLATED[level]; } /** * @param level int in range [0-5] that describes the inflated signal level * @param numberOfLevels one of (5, 6) that describes the default number of levels, or the * inflated number of levels. The level param should be relative to the * number of levels. This won't do any inflation. * @return the appropriate content description for that signal strength, or 0 if the param is * invalid */ public static int getDescriptionForLevel(int level, int numberOfLevels) { if (numberOfLevels == 5) { return getDescriptionForLevel(level); } else if (numberOfLevels == 6) { return getDescriptionForInflatedLevel(level); } else { return 0; } } public static final int[] DATA_CONNECTION_STRENGTH = { R.string.accessibility_no_data, R.string.accessibility_data_one_bar, Loading packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt +22 −8 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH import com.android.settingslib.AccessibilityContentDescriptions import com.android.systemui.Flags.statusBarStaticInoutIndicators import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon Loading Loading @@ -50,7 +50,7 @@ interface MobileIconViewModelCommon { /** True if this view should be visible at all. */ val isVisible: StateFlow<Boolean> val icon: Flow<SignalIconModel> val contentDescription: Flow<ContentDescription> val contentDescription: Flow<ContentDescription?> val roaming: Flow<Boolean> /** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */ val networkTypeIcon: Flow<Icon.Resource?> Loading Loading @@ -123,7 +123,7 @@ class MobileIconViewModel( override val icon: Flow<SignalIconModel> = vmProvider.flatMapLatest { it.icon } override val contentDescription: Flow<ContentDescription> = override val contentDescription: Flow<ContentDescription?> = vmProvider.flatMapLatest { it.contentDescription } override val roaming: Flow<Boolean> = vmProvider.flatMapLatest { it.roaming } Loading Loading @@ -206,12 +206,26 @@ private class CellularIconViewModel( override val icon: Flow<SignalIconModel> = iconInteractor.signalLevelIcon override val contentDescription: Flow<ContentDescription> = run { val initial = ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[0]) override val contentDescription: Flow<ContentDescription?> = iconInteractor.signalLevelIcon .map { ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[it.level]) } .stateIn(scope, SharingStarted.WhileSubscribed(), initial) .map { // We expect the signal icon to be cellular here since this is the cellular vm if (it !is SignalIconModel.Cellular) { null } else { val resId = AccessibilityContentDescriptions.getDescriptionForLevel( it.level, it.numberOfLevels ) if (resId != 0) { ContentDescription.Resource(resId) } else { null } } } .stateIn(scope, SharingStarted.WhileSubscribed(), null) private val showNetworkTypeIcon: Flow<Boolean> = combine( Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt +34 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupReposi import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn Loading Loading @@ -278,6 +279,39 @@ class MobileIconViewModelTest : SysuiTestCase() { job.cancel() } @Test fun contentDescription_nonInflated_invalidLevelIsNull() = testScope.runTest { val latest by collectLastValue(underTest.contentDescription) repository.setAllLevels(-1) assertThat(latest).isNull() repository.setAllLevels(100) assertThat(latest).isNull() } @Test fun contentDescription_nonInflated_testABunchOfLevelsForNull() = testScope.runTest { val latest by collectLastValue(underTest.contentDescription) repository.numberOfLevels.value = 5 // -1 and 5 are out of the bounds for non-inflated content descriptions for (i in -1..5) { repository.setAllLevels(i) when (i) { -1, 5 -> assertWithMessage("Level $i is expected to be null").that(latest).isNull() else -> assertWithMessage("Level $i is expected not to be null") .that(latest) .isNotNull() } } } @Test fun networkType_dataEnabled_groupIsRepresented() = testScope.runTest { Loading Loading
packages/SettingsLib/res/values/strings.xml +2 −0 Original line number Diff line number Diff line Loading @@ -1660,6 +1660,8 @@ <string name="accessibility_phone_two_bars">Phone two bars.</string> <!-- Content description of the phone signal when it is three bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_three_bars">Phone three bars.</string> <!-- Content description of the phone signal when it is four bars for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_four_bars">Phone four bars.</string> <!-- Content description of the phone signal when it is full for accessibility (not shown on the screen). [CHAR LIMIT=NONE] --> <string name="accessibility_phone_signal_full">Phone signal full.</string> Loading
packages/SettingsLib/src/com/android/settingslib/AccessibilityContentDescriptions.java +53 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,59 @@ public class AccessibilityContentDescriptions { R.string.accessibility_phone_signal_full }; /** * @param level int in range [0-4] that describes the signal level * @return the appropriate content description for that signal strength, or 0 if the param is * invalid */ public static int getDescriptionForLevel(int level) { if (level > 4 || level < 0) { return 0; } return PHONE_SIGNAL_STRENGTH[level]; } public static final int[] PHONE_SIGNAL_STRENGTH_INFLATED = { PHONE_SIGNAL_STRENGTH_NONE, R.string.accessibility_phone_one_bar, R.string.accessibility_phone_two_bars, R.string.accessibility_phone_three_bars, R.string.accessibility_phone_four_bars, R.string.accessibility_phone_signal_full }; /** * @param level int in range [0-5] that describes the inflated signal level * @return the appropriate content description for that signal strength, or 0 if the param is * invalid */ public static int getDescriptionForInflatedLevel(int level) { if (level > 5 || level < 0) { return 0; } return PHONE_SIGNAL_STRENGTH_INFLATED[level]; } /** * @param level int in range [0-5] that describes the inflated signal level * @param numberOfLevels one of (5, 6) that describes the default number of levels, or the * inflated number of levels. The level param should be relative to the * number of levels. This won't do any inflation. * @return the appropriate content description for that signal strength, or 0 if the param is * invalid */ public static int getDescriptionForLevel(int level, int numberOfLevels) { if (numberOfLevels == 5) { return getDescriptionForLevel(level); } else if (numberOfLevels == 6) { return getDescriptionForInflatedLevel(level); } else { return 0; } } public static final int[] DATA_CONNECTION_STRENGTH = { R.string.accessibility_no_data, R.string.accessibility_data_one_bar, Loading
packages/SystemUI/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModel.kt +22 −8 Original line number Diff line number Diff line Loading @@ -16,7 +16,7 @@ package com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel import com.android.settingslib.AccessibilityContentDescriptions.PHONE_SIGNAL_STRENGTH import com.android.settingslib.AccessibilityContentDescriptions import com.android.systemui.Flags.statusBarStaticInoutIndicators import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon Loading Loading @@ -50,7 +50,7 @@ interface MobileIconViewModelCommon { /** True if this view should be visible at all. */ val isVisible: StateFlow<Boolean> val icon: Flow<SignalIconModel> val contentDescription: Flow<ContentDescription> val contentDescription: Flow<ContentDescription?> val roaming: Flow<Boolean> /** The RAT icon (LTE, 3G, 5G, etc) to be displayed. Null if we shouldn't show anything */ val networkTypeIcon: Flow<Icon.Resource?> Loading Loading @@ -123,7 +123,7 @@ class MobileIconViewModel( override val icon: Flow<SignalIconModel> = vmProvider.flatMapLatest { it.icon } override val contentDescription: Flow<ContentDescription> = override val contentDescription: Flow<ContentDescription?> = vmProvider.flatMapLatest { it.contentDescription } override val roaming: Flow<Boolean> = vmProvider.flatMapLatest { it.roaming } Loading Loading @@ -206,12 +206,26 @@ private class CellularIconViewModel( override val icon: Flow<SignalIconModel> = iconInteractor.signalLevelIcon override val contentDescription: Flow<ContentDescription> = run { val initial = ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[0]) override val contentDescription: Flow<ContentDescription?> = iconInteractor.signalLevelIcon .map { ContentDescription.Resource(PHONE_SIGNAL_STRENGTH[it.level]) } .stateIn(scope, SharingStarted.WhileSubscribed(), initial) .map { // We expect the signal icon to be cellular here since this is the cellular vm if (it !is SignalIconModel.Cellular) { null } else { val resId = AccessibilityContentDescriptions.getDescriptionForLevel( it.level, it.numberOfLevels ) if (resId != 0) { ContentDescription.Resource(resId) } else { null } } } .stateIn(scope, SharingStarted.WhileSubscribed(), null) private val showNetworkTypeIcon: Flow<Boolean> = combine( Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/mobile/ui/viewmodel/MobileIconViewModelTest.kt +34 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import com.android.systemui.statusbar.policy.data.repository.FakeUserSetupReposi import com.android.systemui.util.CarrierConfigTracker import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.launchIn Loading Loading @@ -278,6 +279,39 @@ class MobileIconViewModelTest : SysuiTestCase() { job.cancel() } @Test fun contentDescription_nonInflated_invalidLevelIsNull() = testScope.runTest { val latest by collectLastValue(underTest.contentDescription) repository.setAllLevels(-1) assertThat(latest).isNull() repository.setAllLevels(100) assertThat(latest).isNull() } @Test fun contentDescription_nonInflated_testABunchOfLevelsForNull() = testScope.runTest { val latest by collectLastValue(underTest.contentDescription) repository.numberOfLevels.value = 5 // -1 and 5 are out of the bounds for non-inflated content descriptions for (i in -1..5) { repository.setAllLevels(i) when (i) { -1, 5 -> assertWithMessage("Level $i is expected to be null").that(latest).isNull() else -> assertWithMessage("Level $i is expected not to be null") .that(latest) .isNotNull() } } } @Test fun networkType_dataEnabled_groupIsRepresented() = testScope.runTest { Loading