summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt34
-rw-r--r--packages/SystemUI/res/values/strings.xml10
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt63
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt4
5 files changed, 88 insertions, 31 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
index a46f4e5fef1a..cb3867f209e3 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlider.kt
@@ -34,12 +34,15 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
+import androidx.compose.ui.semantics.CustomAccessibilityAction
import androidx.compose.ui.semantics.ProgressBarRangeInfo
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
+import androidx.compose.ui.semantics.customActions
import androidx.compose.ui.semantics.disabled
import androidx.compose.ui.semantics.progressBarRangeInfo
import androidx.compose.ui.semantics.setProgress
+import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.unit.dp
import com.android.compose.PlatformSlider
import com.android.compose.PlatformSliderColors
@@ -60,14 +63,31 @@ fun VolumeSlider(
PlatformSlider(
modifier =
modifier.clearAndSetSemantics {
- if (!state.isEnabled) disabled()
- contentDescription =
- state.disabledMessage?.let { "${state.label}, $it" } ?: state.label
-
- // provide a not animated value to the a11y because it fails to announce the
- // settled value when it changes rapidly.
if (state.isEnabled) {
- progressBarRangeInfo = ProgressBarRangeInfo(state.value, state.valueRange)
+ contentDescription = state.label
+ state.a11yClickDescription?.let {
+ customActions =
+ listOf(
+ CustomAccessibilityAction(
+ it,
+ ) {
+ onIconTapped()
+ true
+ }
+ )
+ }
+
+ state.a11yStateDescription?.let { stateDescription = it }
+ ?: run {
+ // provide a not animated value to the a11y because it fails to announce
+ // the settled value when it changes rapidly.
+ progressBarRangeInfo =
+ ProgressBarRangeInfo(state.value, state.valueRange)
+ }
+ } else {
+ disabled()
+ contentDescription =
+ state.disabledMessage?.let { "${state.label}, $it" } ?: state.label
}
setProgress { targetValue ->
val targetDirection =
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 45bcd829336f..9d7a44bd45ec 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1634,9 +1634,15 @@
<string name="volume_panel_collapsed_sliders">Volume sliders collapsed</string>
<!-- Hint for accessibility. A stream name is a parameter. For example: double tap to mute media [CHAR_LIMIT=NONE] -->
- <string name="volume_panel_hint_mute">mute %s</string>
+ <string name="volume_panel_hint_mute">Mute %s</string>
<!-- Hint for accessibility. A stream name is a parameter. For example: double tap to unmute media [CHAR_LIMIT=NONE] -->
- <string name="volume_panel_hint_unmute">unmute %s</string>
+ <string name="volume_panel_hint_unmute">Unmute %s</string>
+
+ <!-- Hint for accessibility. This is announced when the stream is muted [CHAR_LIMIT=NONE] -->
+ <string name="volume_panel_hint_muted">muted</string>
+
+ <!-- Hint for accessibility. This is announced when ring mode is set to Vibrate. [CHAR_LIMIT=NONE] -->
+ <string name="volume_panel_hint_vibrate">vibrate</string>
<!-- Title with application label for media output settings when there is media playing. [CHAR LIMIT=20] -->
<string name="media_output_label_title">Playing <xliff:g id="label" example="Music Player">%s</xliff:g> on</string>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
index 038633810fd7..c08cd64e4e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/AudioStreamSliderViewModel.kt
@@ -49,6 +49,11 @@ constructor(
private val uiEventLogger: UiEventLogger,
) : SliderViewModel {
+ private val streamsAffectedByRing =
+ setOf(
+ AudioManager.STREAM_RING,
+ AudioManager.STREAM_NOTIFICATION,
+ )
private val audioStream = audioStreamWrapper.audioStream
private val iconsByStream =
mapOf(
@@ -125,15 +130,42 @@ constructor(
isEnabled: Boolean,
ringerMode: RingerMode,
): State {
+ val label =
+ labelsByStream[audioStream]?.let(context::getString)
+ ?: error("No label for the stream: $audioStream")
return State(
value = volume.toFloat(),
valueRange = volumeRange.first.toFloat()..volumeRange.last.toFloat(),
icon = getIcon(ringerMode),
- label = labelsByStream[audioStream]?.let(context::getString)
- ?: error("No label for the stream: $audioStream"),
+ label = label,
disabledMessage = disabledTextByStream[audioStream]?.let(context::getString),
isEnabled = isEnabled,
a11yStep = volumeRange.step,
+ a11yClickDescription =
+ context.getString(
+ if (isMuted) {
+ R.string.volume_panel_hint_unmute
+ } else {
+ R.string.volume_panel_hint_mute
+ },
+ label,
+ ),
+ a11yStateDescription =
+ if (volume == volumeRange.first) {
+ context.getString(
+ if (audioStream.value in streamsAffectedByRing) {
+ if (ringerMode.value == AudioManager.RINGER_MODE_VIBRATE) {
+ R.string.volume_panel_hint_vibrate
+ } else {
+ R.string.volume_panel_hint_muted
+ }
+ } else {
+ R.string.volume_panel_hint_muted
+ }
+ )
+ } else {
+ null
+ },
audioStreamModel = this,
isMutable = audioVolumeInteractor.isAffectedByMute(audioStream),
)
@@ -143,27 +175,14 @@ constructor(
val isMutedOrNoVolume = isMuted || volume == minVolume
val iconRes =
if (isMutedOrNoVolume) {
- when (audioStream.value) {
- AudioManager.STREAM_MUSIC -> R.drawable.ic_volume_off
- AudioManager.STREAM_BLUETOOTH_SCO -> R.drawable.ic_volume_off
- AudioManager.STREAM_VOICE_CALL -> R.drawable.ic_volume_off
- AudioManager.STREAM_RING ->
- if (ringerMode.value == AudioManager.RINGER_MODE_VIBRATE) {
- R.drawable.ic_volume_ringer_vibrate
- } else {
- R.drawable.ic_volume_off
- }
- AudioManager.STREAM_NOTIFICATION ->
- if (ringerMode.value == AudioManager.RINGER_MODE_VIBRATE) {
- R.drawable.ic_volume_ringer_vibrate
- } else {
- R.drawable.ic_volume_off
- }
- AudioManager.STREAM_ALARM -> R.drawable.ic_volume_off
- else -> {
- Log.wtf(TAG, "No icon for the stream: $audioStream")
+ if (audioStream.value in streamsAffectedByRing) {
+ if (ringerMode.value == AudioManager.RINGER_MODE_VIBRATE) {
+ R.drawable.ic_volume_ringer_vibrate
+ } else {
R.drawable.ic_volume_off
}
+ } else {
+ R.drawable.ic_volume_off
}
} else {
iconsByStream[audioStream]
@@ -186,6 +205,8 @@ constructor(
override val disabledMessage: String?,
override val isEnabled: Boolean,
override val a11yStep: Int,
+ override val a11yClickDescription: String?,
+ override val a11yStateDescription: String?,
override val isMutable: Boolean,
val audioStreamModel: AudioStreamModel,
) : SliderState
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt
index 956ab66ac0c3..10714d1f41af 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/CastVolumeSliderViewModel.kt
@@ -68,7 +68,7 @@ constructor(
icon = Icon.Resource(R.drawable.ic_cast, null),
label = context.getString(R.string.media_device_cast),
isEnabled = true,
- a11yStep = 1
+ a11yStep = 1,
)
}
@@ -85,6 +85,12 @@ constructor(
override val isMutable: Boolean
get() = false
+
+ override val a11yClickDescription: String?
+ get() = null
+
+ override val a11yStateDescription: String?
+ get() = null
}
@AssistedFactory
diff --git a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt
index d71a9d8dae94..c951928bb977 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt
+++ b/packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/slider/ui/viewmodel/SliderState.kt
@@ -34,6 +34,8 @@ sealed interface SliderState {
* enough to trigger rounding to the correct value.
*/
val a11yStep: Int
+ val a11yClickDescription: String?
+ val a11yStateDescription: String?
val disabledMessage: String?
val isMutable: Boolean
@@ -44,6 +46,8 @@ sealed interface SliderState {
override val label: String = ""
override val disabledMessage: String? = null
override val a11yStep: Int = 0
+ override val a11yClickDescription: String? = null
+ override val a11yStateDescription: String? = null
override val isEnabled: Boolean = true
override val isMutable: Boolean = false
}