Add a content description for the illustration if it is an animation
Since `isAnimatable` is decided in `onBindViewHolder`, we need to register
an onBindListener and update the content description if the current
illustration is an animation.
For the static images, we would like to skip them in Talkback since they
are decorative images.
Bug: 395882764
Test: manually. attach screenshot to the bug
Test: atest ToggleFeaturePreferenceFragmentTest
flag: EXEMPT. bugfix
Change-Id: I57bf96d0891ba553ef29d25ae9489f34b2a832e9
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 003cd9b..24839ff 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -14293,4 +14293,6 @@
<string name="supervision_add_forgot_pin_preference_title">Forgot PIN</string>
<!-- Title for web content filters entry [CHAR LIMIT=60] -->
<string name="supervision_web_content_filters_title">Web content filters</string>
+ <!-- Generic content description that is attached to the preview illustration at the top of an Accessibility feature toggle page. [CHAR LIMIT=NONE] -->
+ <string name="accessibility_illustration_content_description"><xliff:g id="feature" example="Select to Speak">%1$s</xliff:g> animation</string>
</resources>
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 66c32df..d8c3985 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -68,6 +68,7 @@
import com.android.settings.flags.Flags;
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settings.widget.SettingsMainSwitchPreference;
+import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.widget.IllustrationPreference;
import com.android.settingslib.widget.TopIntroPreference;
@@ -311,6 +312,11 @@
return getString(R.string.accessibility_shortcut_title, mFeatureName);
}
+ @VisibleForTesting
+ CharSequence getContentDescriptionForAnimatedIllustration() {
+ return getString(R.string.accessibility_illustration_content_description, mFeatureName);
+ }
+
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
}
@@ -427,22 +433,38 @@
return drawable;
}
-
private void initAnimatedImagePreference() {
- if (mImageUri == null) {
+ initAnimatedImagePreference(mImageUri, new IllustrationPreference(getPrefContext()));
+ }
+
+ @VisibleForTesting
+ void initAnimatedImagePreference(
+ @Nullable Uri imageUri,
+ @NonNull IllustrationPreference preference) {
+ if (imageUri == null) {
return;
}
final int displayHalfHeight =
AccessibilityUtil.getDisplayBounds(getPrefContext()).height() / 2;
- final IllustrationPreference illustrationPreference =
- new IllustrationPreference(getPrefContext());
- illustrationPreference.setImageUri(mImageUri);
- illustrationPreference.setSelectable(false);
- illustrationPreference.setMaxHeight(displayHalfHeight);
- illustrationPreference.setKey(KEY_ANIMATED_IMAGE);
-
- getPreferenceScreen().addPreference(illustrationPreference);
+ preference.setImageUri(imageUri);
+ preference.setSelectable(false);
+ preference.setMaxHeight(displayHalfHeight);
+ preference.setKey(KEY_ANIMATED_IMAGE);
+ preference.setOnBindListener(view -> {
+ // isAnimatable is decided in
+ // {@link IllustrationPreference#onBindViewHolder(PreferenceViewHolder)}. Therefore, we
+ // wait until the view is bond to set the content description for it.
+ // The content description is added for an animation illustration only. Since the static
+ // images are decorative.
+ ThreadUtils.getUiThreadHandler().post(() -> {
+ if (preference.isAnimatable()) {
+ preference.setContentDescription(
+ getContentDescriptionForAnimatedIllustration());
+ }
+ });
+ });
+ getPreferenceScreen().addPreference(preference);
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index 571075c..f72b591 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -39,6 +39,7 @@
import android.content.Intent;
import android.content.pm.PackageManager;
import android.icu.text.CaseMap;
+import android.net.Uri;
import android.os.Bundle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
@@ -56,12 +57,14 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
+import androidx.preference.PreferenceViewHolder;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.testutils.shadow.ShadowAccessibilityManager;
import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settingslib.widget.IllustrationPreference;
import com.android.settingslib.widget.TopIntroPreference;
import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -79,6 +82,7 @@
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import org.robolectric.shadows.ShadowApplication;
+import org.robolectric.shadows.ShadowLooper;
import java.util.List;
import java.util.Locale;
@@ -316,6 +320,45 @@
}
@Test
+ public void initAnimatedImagePreference_isAnimatable_setContentDescription() {
+ mFragment.mFeatureName = "Test Feature";
+ final View view =
+ LayoutInflater.from(mContext).inflate(
+ com.android.settingslib.widget.preference.illustration
+ .R.layout.illustration_preference,
+ null);
+ IllustrationPreference preference = spy(new IllustrationPreference(mFragment.getContext()));
+ when(preference.isAnimatable()).thenReturn(true);
+ mFragment.initAnimatedImagePreference(mock(Uri.class), preference);
+
+ preference.onBindViewHolder(PreferenceViewHolder.createInstanceForTests(view));
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+
+ String expectedContentDescription = mFragment.getString(
+ R.string.accessibility_illustration_content_description, mFragment.mFeatureName);
+ assertThat(preference.getContentDescription().toString())
+ .isEqualTo(expectedContentDescription);
+ }
+
+ @Test
+ public void initAnimatedImagePreference_isNotAnimatable_notSetContentDescription() {
+ mFragment.mFeatureName = "Test Feature";
+ final View view =
+ LayoutInflater.from(mContext).inflate(
+ com.android.settingslib.widget.preference.illustration
+ .R.layout.illustration_preference,
+ null);
+ IllustrationPreference preference = spy(new IllustrationPreference(mFragment.getContext()));
+ when(preference.isAnimatable()).thenReturn(false);
+ mFragment.initAnimatedImagePreference(mock(Uri.class), preference);
+
+ preference.onBindViewHolder(PreferenceViewHolder.createInstanceForTests(view));
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+
+ verify(preference, never()).setContentDescription(any());
+ }
+
+ @Test
@EnableFlags(Flags.FLAG_ACCESSIBILITY_SHOW_APP_INFO_BUTTON)
public void createAppInfoPreference_withValidComponentName() {
when(mPackageManager.isPackageAvailable(PLACEHOLDER_PACKAGE_NAME)).thenReturn(true);