Merge "Add a content description for the illustration if it is an animation" into main
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 0f51ddd..6071b06 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -14297,4 +14297,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);