Add content description to volume title in settings.
Adds content description that is announced by talkback when a11y focus is on volume preference. This improves talkback announcement when view changes. Fixes: 285529113 Bug: 285455826 Fixes: 285487766 Test: atest VolumeSeekBarPreferenceControllerTest Test: atest VolumeSeekBarPreferenceTest Change-Id: Ibe80b4b1d489dc058df1cc79c96b034d5ddc6e56
This commit is contained in:
@@ -52,6 +52,7 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
||||
|
||||
public MediaVolumePreferenceController(Context context) {
|
||||
super(context, KEY_MEDIA_VOLUME);
|
||||
mVolumePreferenceListener = this::updateContentDescription;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,6 +110,18 @@ public class MediaVolumePreferenceController extends VolumeSeekBarPreferenceCont
|
||||
return false;
|
||||
}
|
||||
|
||||
private void updateContentDescription() {
|
||||
if (mPreference != null) {
|
||||
if (mPreference.isMuted()) {
|
||||
mPreference.updateContentDescription(
|
||||
mContext.getString(R.string.volume_content_description_silent_mode,
|
||||
mPreference.getTitle()));
|
||||
} else {
|
||||
mPreference.updateContentDescription(mPreference.getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SliceAction getSliceEndItem(Context context) {
|
||||
if (!isSupportEndItem()) {
|
||||
|
@@ -75,6 +75,7 @@ public class NotificationVolumePreferenceController extends
|
||||
|
||||
updateEffectsSuppressor();
|
||||
selectPreferenceIconState();
|
||||
updateContentDescription();
|
||||
updateEnabledState();
|
||||
}
|
||||
|
||||
@@ -120,23 +121,32 @@ public class NotificationVolumePreferenceController extends
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void selectPreferenceIconState() {
|
||||
protected int getEffectiveRingerMode() {
|
||||
if (mVibrator == null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
return AudioManager.RINGER_MODE_SILENT;
|
||||
} else if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
|
||||
if (mHelper.getStreamVolume(AudioManager.STREAM_NOTIFICATION) == 0) {
|
||||
// Ring is in normal, but notification is in silent.
|
||||
return AudioManager.RINGER_MODE_SILENT;
|
||||
}
|
||||
}
|
||||
return mRingerMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateContentDescription() {
|
||||
if (mPreference != null) {
|
||||
if (mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
mMuteIcon = mVibrateIconId;
|
||||
mPreference.showIcon(mVibrateIconId);
|
||||
} else if (mRingerMode == AudioManager.RINGER_MODE_SILENT
|
||||
|| mVibrator == null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
mMuteIcon = mSilentIconId;
|
||||
mPreference.showIcon(mSilentIconId);
|
||||
} else { // ringmode normal: could be that we are still silent
|
||||
if (mHelper.getStreamVolume(AudioManager.STREAM_NOTIFICATION) == 0) {
|
||||
// ring is in normal, but notification is in silent
|
||||
mMuteIcon = mSilentIconId;
|
||||
mPreference.showIcon(mSilentIconId);
|
||||
} else {
|
||||
mPreference.showIcon(mNormalIconId);
|
||||
}
|
||||
int ringerMode = getEffectiveRingerMode();
|
||||
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
mPreference.updateContentDescription(
|
||||
mContext.getString(
|
||||
R.string.notification_volume_content_description_vibrate_mode));
|
||||
} else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
|
||||
mPreference.updateContentDescription(
|
||||
mContext.getString(R.string.volume_content_description_silent_mode,
|
||||
mPreference.getTitle()));
|
||||
} else {
|
||||
mPreference.updateContentDescription(mPreference.getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -169,6 +179,7 @@ public class NotificationVolumePreferenceController extends
|
||||
break;
|
||||
case NOTIFICATION_VOLUME_CHANGED:
|
||||
selectPreferenceIconState();
|
||||
updateContentDescription();
|
||||
updateEnabledState();
|
||||
break;
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ import android.os.Vibrator;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.settings.R;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -54,6 +55,7 @@ public abstract class RingerModeAffectedVolumePreferenceController extends
|
||||
if (mVibrator != null && !mVibrator.hasVibrator()) {
|
||||
mVibrator = null;
|
||||
}
|
||||
mVolumePreferenceListener = this::updateContentDescription;
|
||||
}
|
||||
|
||||
protected void updateEffectsSuppressor() {
|
||||
@@ -123,6 +125,7 @@ public abstract class RingerModeAffectedVolumePreferenceController extends
|
||||
}
|
||||
mRingerMode = ringerMode;
|
||||
selectPreferenceIconState();
|
||||
updateContentDescription();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -131,10 +134,11 @@ public abstract class RingerModeAffectedVolumePreferenceController extends
|
||||
*/
|
||||
protected void selectPreferenceIconState() {
|
||||
if (mPreference != null) {
|
||||
if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
|
||||
int ringerMode = getEffectiveRingerMode();
|
||||
if (ringerMode == AudioManager.RINGER_MODE_NORMAL) {
|
||||
mPreference.showIcon(mNormalIconId);
|
||||
} else {
|
||||
if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE && mVibrator != null) {
|
||||
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
mMuteIcon = mVibrateIconId;
|
||||
} else {
|
||||
mMuteIcon = mSilentIconId;
|
||||
@@ -144,6 +148,28 @@ public abstract class RingerModeAffectedVolumePreferenceController extends
|
||||
}
|
||||
}
|
||||
|
||||
protected int getEffectiveRingerMode() {
|
||||
if (mVibrator == null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
return AudioManager.RINGER_MODE_SILENT;
|
||||
}
|
||||
return mRingerMode;
|
||||
}
|
||||
|
||||
protected void updateContentDescription() {
|
||||
if (mPreference != null) {
|
||||
int ringerMode = getEffectiveRingerMode();
|
||||
if (ringerMode == AudioManager.RINGER_MODE_VIBRATE) {
|
||||
mPreference.updateContentDescription(
|
||||
mContext.getString(R.string.ringer_content_description_vibrate_mode));
|
||||
} else if (ringerMode == AudioManager.RINGER_MODE_SILENT) {
|
||||
mPreference.updateContentDescription(
|
||||
mContext.getString(R.string.ringer_content_description_silent_mode));
|
||||
} else {
|
||||
mPreference.updateContentDescription(mPreference.getTitle());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract boolean hintsMatch(int hints);
|
||||
|
||||
}
|
||||
|
@@ -65,6 +65,7 @@ public class SeparateRingVolumePreferenceController extends
|
||||
mReceiver.register(true);
|
||||
updateEffectsSuppressor();
|
||||
selectPreferenceIconState();
|
||||
updateContentDescription();
|
||||
|
||||
if (mPreference != null) {
|
||||
mPreference.setVisible(getAvailabilityStatus() == AVAILABLE);
|
||||
|
@@ -47,10 +47,13 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
|
||||
protected SeekBar mSeekBar;
|
||||
private int mStream;
|
||||
private SeekBarVolumizer mVolumizer;
|
||||
@VisibleForTesting
|
||||
SeekBarVolumizer mVolumizer;
|
||||
private Callback mCallback;
|
||||
private Listener mListener;
|
||||
private ImageView mIconView;
|
||||
private TextView mSuppressionTextView;
|
||||
private TextView mTitle;
|
||||
private String mSuppressionText;
|
||||
private boolean mMuted;
|
||||
private boolean mZenMuted;
|
||||
@@ -98,6 +101,10 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public void setListener(Listener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
public void onActivityResume() {
|
||||
if (mStopped) {
|
||||
init();
|
||||
@@ -118,6 +125,7 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
mSeekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
|
||||
mIconView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
|
||||
mSuppressionTextView = (TextView) view.findViewById(R.id.suppression_text);
|
||||
mTitle = (TextView) view.findViewById(com.android.internal.R.id.title);
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -142,6 +150,9 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
mMuted = muted;
|
||||
mZenMuted = zenMuted;
|
||||
updateIconView();
|
||||
if (mListener != null) {
|
||||
mListener.onUpdateMuteState();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onStartTrackingTouch(SeekBarVolumizer sbv) {
|
||||
@@ -165,6 +176,9 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
mVolumizer.setSeekBar(mSeekBar);
|
||||
updateIconView();
|
||||
updateSuppressionText();
|
||||
if (mListener != null) {
|
||||
mListener.onUpdateMuteState();
|
||||
}
|
||||
if (!isEnabled()) {
|
||||
mSeekBar.setEnabled(false);
|
||||
mVolumizer.stop();
|
||||
@@ -175,7 +189,7 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
if (mIconView == null) return;
|
||||
if (mIconResId != 0) {
|
||||
mIconView.setImageResource(mIconResId);
|
||||
} else if (mMuteIconResId != 0 && mMuted && !mZenMuted) {
|
||||
} else if (mMuteIconResId != 0 && isMuted()) {
|
||||
mIconView.setImageResource(mMuteIconResId);
|
||||
} else {
|
||||
mIconView.setImageDrawable(getIcon());
|
||||
@@ -208,6 +222,10 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
updateSuppressionText();
|
||||
}
|
||||
|
||||
protected boolean isMuted() {
|
||||
return mMuted && !mZenMuted;
|
||||
}
|
||||
|
||||
protected void updateSuppressionText() {
|
||||
if (mSuppressionTextView != null && mSeekBar != null) {
|
||||
mSuppressionTextView.setText(mSuppressionText);
|
||||
@@ -216,6 +234,14 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update content description of title to improve talkback announcements.
|
||||
*/
|
||||
protected void updateContentDescription(CharSequence contentDescription) {
|
||||
if (mTitle == null) return;
|
||||
mTitle.setContentDescription(contentDescription);
|
||||
}
|
||||
|
||||
public interface Callback {
|
||||
void onSampleStarting(SeekBarVolumizer sbv);
|
||||
void onStreamValueChanged(int stream, int progress);
|
||||
@@ -225,4 +251,15 @@ public class VolumeSeekBarPreference extends SeekBarPreference {
|
||||
*/
|
||||
void onStartTrackingTouch(SeekBarVolumizer sbv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener to view updates in volumeSeekbarPreference.
|
||||
*/
|
||||
public interface Listener {
|
||||
|
||||
/**
|
||||
* Listener to mute state updates.
|
||||
*/
|
||||
void onUpdateMuteState();
|
||||
}
|
||||
}
|
||||
|
@@ -36,6 +36,7 @@ public abstract class VolumeSeekBarPreferenceController extends
|
||||
protected VolumeSeekBarPreference mPreference;
|
||||
protected VolumeSeekBarPreference.Callback mVolumePreferenceCallback;
|
||||
protected AudioHelper mHelper;
|
||||
protected VolumeSeekBarPreference.Listener mVolumePreferenceListener;
|
||||
|
||||
public VolumeSeekBarPreferenceController(Context context, String key) {
|
||||
super(context, key);
|
||||
@@ -62,6 +63,7 @@ public abstract class VolumeSeekBarPreferenceController extends
|
||||
protected void setupVolPreference(PreferenceScreen screen) {
|
||||
mPreference = screen.findPreference(getPreferenceKey());
|
||||
mPreference.setCallback(mVolumePreferenceCallback);
|
||||
mPreference.setListener(mVolumePreferenceListener);
|
||||
mPreference.setStream(getAudioStream());
|
||||
mPreference.setMuteIcon(getMuteIcon());
|
||||
}
|
||||
|
Reference in New Issue
Block a user