Merge "Add switch preference for Audio Description."
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 559a589..16658f8 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -2885,6 +2885,22 @@
         priority="4"
         summary="Using hardcoded color"
         explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
+        errorLine1="            android:color="@color/accessibility_feature_background"/>"
+        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        <location
+            file="res/drawable/ic_audio_description.xml"
+            line="22"
+            column="13"/>
+    </issue>
+
+    <issue
+        id="HardCodedColor"
+        severity="Error"
+        message="Avoid using hardcoded color"
+        category="Correctness"
+        priority="4"
+        summary="Using hardcoded color"
+        explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.&#xA;This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
         errorLine1="        android:fillColor=&quot;@color/battery_good_color_light&quot;"
         errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
         <location
diff --git a/res/drawable/ic_audio_description.xml b/res/drawable/ic_audio_description.xml
new file mode 100644
index 0000000..0226582
--- /dev/null
+++ b/res/drawable/ic_audio_description.xml
@@ -0,0 +1,35 @@
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item>
+        <com.android.settingslib.widget.AdaptiveIconShapeDrawable
+            android:width="@dimen/accessibility_icon_size"
+            android:height="@dimen/accessibility_icon_size"
+            android:color="@color/accessibility_feature_background"/>
+    </item>
+    <item android:gravity="center">
+        <vector
+            android:width="@dimen/accessibility_icon_foreground_size"
+            android:height="@dimen/accessibility_icon_foreground_size"
+            android:viewportWidth="24"
+            android:viewportHeight="24">
+            <path
+                android:fillColor="@android:color/white"
+                android:pathData="M10,18v-4L8,14v-2q0,-1.65 1.175,-2.825Q10.35,8 12,8q1.65,0 2.825,1.175Q16,10.35 16,12v2h-2v4h2.8q0.5,0 0.85,-0.35t0.35,-0.85L18,12q0,-2.5 -1.75,-4.25T12,6Q9.5,6 7.75,7.75T6,12v4.8q0,0.5 0.35,0.85t0.85,0.35zM5,21q-0.825,0 -1.413,-0.587Q3,19.825 3,19L3,5q0,-0.825 0.587,-1.413Q4.175,3 5,3h14q0.825,0 1.413,0.587Q21,4.175 21,5v14q0,0.825 -0.587,1.413Q19.825,21 19,21zM5,19h14L19,5L5,5v14zM5,19L5,5v14z"/>
+        </vector>
+    </item>
+</layer-list>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5cbdb60..a829847 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -5554,6 +5554,13 @@
     </plurals>
     <!-- Title for the accessibility audio adjustment page. [CHAR LIMIT=50] -->
     <string name="accessibility_audio_adjustment_title">Audio adjustment</string>
+    <!-- Title for control audio description preference. [CHAR LIMIT=50] -->
+    <string name="accessibility_toggle_audio_description_preference_title">Audio Description</string>
+    <!-- Summary for accessibility preference for audio description when need
+    audio description in adopted apps. [CHAR_LIMIT=NONE] -->
+    <string name="accessibility_audio_description_summary">Select audio sound track with audio description by default</string>
+    <!-- List of synonyms used in the settings search bar to find the "Audio Description. [CHAR LIMIT=NONE] -->
+    <string name="keywords_audio_description">audio description, audio, description, low vision,</string>
 
     <!-- Preference's shortcut when enabled. [CHAR LIMIT=NONE] -->
     <string name="accessibility_summary_shortcut_enabled">Shortcut on</string>
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index dcf3fc2..fcdf47b 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -81,6 +81,16 @@
             settings:keywords="@string/keywords_magnification"
             settings:controller="com.android.settings.accessibility.MagnificationPreferenceController"/>
 
+        <SwitchPreference
+            android:key="toggle_audio_description"
+            android:persistent="false"
+            android:icon="@drawable/ic_audio_description"
+            android:summary="@string/accessibility_audio_description_summary"
+            android:title="@string/accessibility_toggle_audio_description_preference_title"
+            settings:keywords="@string/keywords_audio_description"
+            settings:searchable="true"
+            settings:controller="com.android.settings.accessibility.AudioDescriptionPreferenceController"/>
+
     </PreferenceCategory>
 
     <PreferenceCategory
diff --git a/src/com/android/settings/accessibility/AudioDescriptionPreferenceController.java b/src/com/android/settings/accessibility/AudioDescriptionPreferenceController.java
new file mode 100644
index 0000000..a05a0d0
--- /dev/null
+++ b/src/com/android/settings/accessibility/AudioDescriptionPreferenceController.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static android.provider.Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT;
+
+import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+
+import android.content.Context;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * A toggle preference controller for audio description
+ */
+public class AudioDescriptionPreferenceController extends TogglePreferenceController {
+
+    static final String PREF_KEY = "toggle_audio_description";
+
+    public AudioDescriptionPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public boolean isChecked() {
+        return Settings.Secure.getIntForUser(mContext.getContentResolver(),
+                ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT,
+                OFF /* default */,
+                UserHandle.USER_CURRENT) == ON;
+    }
+
+    @Override
+    public boolean setChecked(boolean isChecked) {
+        return Settings.Secure.putIntForUser(mContext.getContentResolver(),
+                ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT,
+                isChecked ? ON : OFF,
+                UserHandle.USER_CURRENT);
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return AVAILABLE;
+    }
+
+    @Override
+    public int getSliceHighlightMenuRes() {
+        return R.string.menu_key_accessibility;
+    }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AudioDescriptionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AudioDescriptionPreferenceControllerTest.java
new file mode 100644
index 0000000..1d3ffa8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/accessibility/AudioDescriptionPreferenceControllerTest.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.accessibility;
+
+import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
+import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+
+@RunWith(RobolectricTestRunner.class)
+public class AudioDescriptionPreferenceControllerTest {
+
+    private static final String KEY_AUDIO_DESCRIPTION =
+            Settings.Secure.ENABLED_ACCESSIBILITY_AUDIO_DESCRIPTION_BY_DEFAULT;
+    private static final int UNKNOWN = -1;
+
+    private final Context mContext = ApplicationProvider.getApplicationContext();
+    private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
+    private final AudioDescriptionPreferenceController mController =
+            new AudioDescriptionPreferenceController(mContext,
+                    AudioDescriptionPreferenceController.PREF_KEY);
+
+    @Before
+    public void setUp() {
+        final PreferenceManager preferenceManager = new PreferenceManager(mContext);
+        final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
+        mSwitchPreference.setKey(AudioDescriptionPreferenceController.PREF_KEY);
+        screen.addPreference(mSwitchPreference);
+        mController.displayPreference(screen);
+    }
+
+    @Test
+    public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
+        assertThat(mController.getAvailabilityStatus()).isEqualTo(
+                BasePreferenceController.AVAILABLE);
+    }
+
+    @Test
+    public void isChecked_disableAudioDescription_onResumeShouldReturnFalse() {
+        Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, OFF);
+
+        mController.updateState(mSwitchPreference);
+
+        assertThat(mController.isChecked()).isFalse();
+        assertThat(mSwitchPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void isChecked_enableAudioDescription_onResumeShouldReturnTrue() {
+        Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, ON);
+
+        mController.updateState(mSwitchPreference);
+
+        assertThat(mController.isChecked()).isTrue();
+        assertThat(mSwitchPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void performClick_enableAudioDescription_shouldReturnTrue() {
+        Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, OFF);
+
+        mController.updateState(mSwitchPreference);
+
+        mSwitchPreference.performClick();
+
+        verify(mSwitchPreference).setChecked(true);
+        assertThat(mController.isChecked()).isTrue();
+        assertThat(mSwitchPreference.isChecked()).isTrue();
+    }
+
+    @Test
+    public void performClick_disableAudioDescription_shouldReturnFalse() {
+        Settings.Secure.putInt(mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, ON);
+
+        mController.updateState(mSwitchPreference);
+
+        mSwitchPreference.performClick();
+
+        verify(mSwitchPreference).setChecked(false);
+        assertThat(mController.isChecked()).isFalse();
+        assertThat(mSwitchPreference.isChecked()).isFalse();
+    }
+
+    @Test
+    public void setChecked_setFalse_shouldDisableAudioDescription() {
+        mController.setChecked(false);
+
+        assertThat(Settings.Secure.getInt(
+            mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, UNKNOWN)).isEqualTo(OFF);
+    }
+
+    @Test
+    public void setChecked_setTrue_shouldEnableAudioDescription() {
+        mController.setChecked(true);
+
+        assertThat(Settings.Secure.getInt(
+            mContext.getContentResolver(), KEY_AUDIO_DESCRIPTION, UNKNOWN)).isEqualTo(ON);
+    }
+}