diff --git a/res/xml/accessibility_autoclick_settings.xml b/res/xml/accessibility_autoclick_settings.xml index d387b580d38..ee27cea24e5 100644 --- a/res/xml/accessibility_autoclick_settings.xml +++ b/res/xml/accessibility_autoclick_settings.xml @@ -60,10 +60,11 @@ settings:allowDividerBelow="true" settings:controller="com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController" /> - - + settings:searchable="false" + settings:controller="com.android.settings.accessibility.ToggleAutoclickFooterPreferenceController"/> diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml index bb16f0397cd..4732da5526e 100644 --- a/res/xml/accessibility_button_settings.xml +++ b/res/xml/accessibility_button_settings.xml @@ -59,11 +59,11 @@ android:persistent="false" settings:controller="com.android.settings.accessibility.FloatingMenuOpacityPreferenceController"/> - - - \ No newline at end of file + settings:controller="com.android.settings.accessibility.AccessibilityButtonFooterPreferenceController"/> + diff --git a/res/xml/accessibility_control_timeout_settings.xml b/res/xml/accessibility_control_timeout_settings.xml index 0f14cd5c9c0..71a6605df98 100644 --- a/res/xml/accessibility_control_timeout_settings.xml +++ b/res/xml/accessibility_control_timeout_settings.xml @@ -55,8 +55,11 @@ android:title="@string/accessibility_timeout_2mins" android:persistent="false" /> - - + android:persistent="false" + android:selectable="false" + settings:searchable="false" + settings:controller="com.android.settings.accessibility.AccessibilityControlTimeoutFooterPreferenceController"/> diff --git a/res/xml/captioning_appearance.xml b/res/xml/captioning_appearance.xml index 3e0e804e535..71566307eba 100644 --- a/res/xml/captioning_appearance.xml +++ b/res/xml/captioning_appearance.xml @@ -87,8 +87,11 @@ - - + android:persistent="false" + android:selectable="false" + settings:searchable="false" + settings:controller="com.android.settings.accessibility.CaptionFooterPreferenceController"/> diff --git a/res/xml/captioning_more_options.xml b/res/xml/captioning_more_options.xml index d4111d27d73..b902c48a952 100644 --- a/res/xml/captioning_more_options.xml +++ b/res/xml/captioning_more_options.xml @@ -25,8 +25,12 @@ android:summary="%s" android:title="@string/captioning_locale" /> - + android:persistent="false" + android:selectable="false" + settings:searchable="false" + settings:controller="com.android.settings.accessibility.CaptionFooterPreferenceController"/> diff --git a/res/xml/captioning_settings.xml b/res/xml/captioning_settings.xml index a58e2243075..30e76de506f 100644 --- a/res/xml/captioning_settings.xml +++ b/res/xml/captioning_settings.xml @@ -47,10 +47,12 @@ android:persistent="false" android:title="@string/captioning_more_options_title" /> - + settings:searchable="false" + settings:controller="com.android.settings.accessibility.CaptionFooterPreferenceController"/> diff --git a/src/com/android/settings/accessibility/AccessibilityButtonFooterPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityButtonFooterPreferenceController.java new file mode 100644 index 00000000000..744a29211cf --- /dev/null +++ b/src/com/android/settings/accessibility/AccessibilityButtonFooterPreferenceController.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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 android.content.Context; + +import com.android.settings.R; + +/** + * Preference controller for accessibility button footer. + */ +public class AccessibilityButtonFooterPreferenceController extends + AccessibilityFooterPreferenceController { + + public AccessibilityButtonFooterPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + protected String getLabelName() { + return mContext.getString(R.string.accessibility_button_title); + } +} diff --git a/src/com/android/settings/accessibility/AccessibilityButtonFragment.java b/src/com/android/settings/accessibility/AccessibilityButtonFragment.java index c3e683a5892..4e067d8e293 100644 --- a/src/com/android/settings/accessibility/AccessibilityButtonFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityButtonFragment.java @@ -17,7 +17,6 @@ package com.android.settings.accessibility; import android.app.settings.SettingsEnums; -import android.content.Context; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; @@ -35,11 +34,6 @@ public class AccessibilityButtonFragment extends DashboardFragment { return R.xml.accessibility_button_settings; } - @Override - public void onAttach(Context context) { - super.onAttach(context); - } - @Override protected String getLogTag() { return TAG; diff --git a/src/com/android/settings/accessibility/AccessibilityControlTimeoutFooterPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityControlTimeoutFooterPreferenceController.java new file mode 100644 index 00000000000..ef674288c4d --- /dev/null +++ b/src/com/android/settings/accessibility/AccessibilityControlTimeoutFooterPreferenceController.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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 android.content.Context; + +import com.android.settings.R; + +/** + * Preference controller for accessibility control timeout footer. + */ +public class AccessibilityControlTimeoutFooterPreferenceController extends + AccessibilityFooterPreferenceController { + + public AccessibilityControlTimeoutFooterPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + protected String getLabelName() { + return mContext.getString(R.string.accessibility_setting_item_control_timeout_title); + } +} diff --git a/src/com/android/settings/accessibility/AccessibilityFooterPreference.java b/src/com/android/settings/accessibility/AccessibilityFooterPreference.java new file mode 100644 index 00000000000..899ffa5ceb7 --- /dev/null +++ b/src/com/android/settings/accessibility/AccessibilityFooterPreference.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2021 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 android.content.Context; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.util.AttributeSet; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.preference.PreferenceViewHolder; + +import com.android.settingslib.R; +import com.android.settingslib.widget.FooterPreference; + +/** + * A custom preference acting as footer of a page. It has a field for icon and text. It is added + * to screen as the last preference and groups of icon and text content in accessibility-focusable + * {@link android.view.accessibility.AccessibilityNodeInfo} for TalkBack to use. + */ +public final class AccessibilityFooterPreference extends FooterPreference { + + private CharSequence mIconContentDescription; + private boolean mLinkEnabled; + + public AccessibilityFooterPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public AccessibilityFooterPreference(Context context) { + super(context); + } + + @Override + public void onBindViewHolder(PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + + final TextView title = holder.itemView.findViewById(android.R.id.title); + if (mLinkEnabled) { + // When a TextView has a movement method, it will set the view to clickable. This makes + // View.onTouchEvent always return true and consumes the touch event, essentially + // nullifying any return values of MovementMethod.onTouchEvent. + // To still allow propagating touch events to the parent when this view doesn't have + // links, we only set the movement method here if the text contains links. + title.setMovementMethod(LinkMovementMethod.getInstance()); + } else { + title.setMovementMethod(/* movement= */ null); + } + + final LinearLayout infoFrame = holder.itemView.findViewById(R.id.icon_frame); + if (!TextUtils.isEmpty(mIconContentDescription)) { + // Groups related content. + infoFrame.setContentDescription(mIconContentDescription); + title.setFocusable(false); + } else { + infoFrame.setContentDescription(null); + title.setFocusable(true); + } + } + + /** + * Sets the content description of the icon. + */ + public void setIconContentDescription(CharSequence iconContentDescription) { + if (!TextUtils.equals(iconContentDescription, mIconContentDescription)) { + mIconContentDescription = iconContentDescription; + notifyChanged(); + } + } + + /** + * Gets the content description of the icon. + */ + public CharSequence getIconContentDescription() { + return mIconContentDescription; + } + + /** + * Sets the title field supports movement method. + */ + public void setLinkEnabled(boolean enabled) { + if (mLinkEnabled != enabled) { + mLinkEnabled = enabled; + notifyChanged(); + } + } + + /** + * Returns true if the title field supports movement method. + */ + public boolean isLinkEnabled() { + return mLinkEnabled; + } +} diff --git a/src/com/android/settings/accessibility/AccessibilityFooterPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityFooterPreferenceController.java new file mode 100644 index 00000000000..df01e3bda30 --- /dev/null +++ b/src/com/android/settings/accessibility/AccessibilityFooterPreferenceController.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 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 android.content.Context; + +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +/** + * Base class for accessibility preference footer. + */ +public abstract class AccessibilityFooterPreferenceController extends BasePreferenceController { + + public AccessibilityFooterPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + final AccessibilityFooterPreference footerPreference = + screen.findPreference(getPreferenceKey()); + updateFooterPreferences(footerPreference); + } + + + /** Returns the accessibility feature name. */ + protected abstract String getLabelName(); + + private void updateFooterPreferences(AccessibilityFooterPreference footerPreference) { + final String iconContentDescription = mContext.getString( + R.string.accessibility_introduction_title, getLabelName()); + footerPreference.setIconContentDescription(iconContentDescription); + } +} diff --git a/src/com/android/settings/accessibility/CaptionAppearanceFragment.java b/src/com/android/settings/accessibility/CaptionAppearanceFragment.java index d780ac5d87f..7eceb7d5b28 100644 --- a/src/com/android/settings/accessibility/CaptionAppearanceFragment.java +++ b/src/com/android/settings/accessibility/CaptionAppearanceFragment.java @@ -33,8 +33,8 @@ import androidx.preference.PreferenceCategory; import com.android.internal.widget.SubtitleView; import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; import com.android.settings.accessibility.ListDialogPreference.OnValueChangedListener; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.accessibility.AccessibilityUtils; import com.android.settingslib.search.SearchIndexable; @@ -46,8 +46,10 @@ import java.util.Locale; /** Settings fragment containing font style of captioning properties. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class CaptionAppearanceFragment extends SettingsPreferenceFragment +public class CaptionAppearanceFragment extends DashboardFragment implements OnPreferenceChangeListener, OnValueChangedListener { + + private static final String TAG = "CaptionAppearanceFragment"; private static final String PREF_CAPTION_PREVIEW = "caption_preview"; private static final String PREF_BACKGROUND_COLOR = "captioning_background_color"; private static final String PREF_BACKGROUND_OPACITY = "captioning_background_opacity"; @@ -107,12 +109,11 @@ public class CaptionAppearanceFragment extends SettingsPreferenceFragment } @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + super.onCreatePreferences(savedInstanceState, rootKey); mCaptioningManager = (CaptioningManager) getSystemService(Context.CAPTIONING_SERVICE); - addPreferencesFromResource(R.xml.captioning_appearance); initializeAllPreferences(); updateAllPreferences(); refreshShowingCustom(); @@ -120,6 +121,16 @@ public class CaptionAppearanceFragment extends SettingsPreferenceFragment refreshPreviewText(); } + @Override + protected int getPreferenceScreenResId() { + return R.xml.captioning_appearance; + } + + @Override + protected String getLogTag() { + return TAG; + } + private void refreshPreviewText() { final Context context = getActivity(); if (context == null) { diff --git a/src/com/android/settings/accessibility/CaptionFooterPreferenceController.java b/src/com/android/settings/accessibility/CaptionFooterPreferenceController.java new file mode 100644 index 00000000000..7ca1d820f06 --- /dev/null +++ b/src/com/android/settings/accessibility/CaptionFooterPreferenceController.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2021 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 android.content.Context; + +import com.android.settings.R; + +/** + * Preference controller for caption footer. + */ +public class CaptionFooterPreferenceController extends AccessibilityFooterPreferenceController { + + public CaptionFooterPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + protected String getLabelName() { + return mContext.getString(R.string.accessibility_captioning_title); + } +} diff --git a/src/com/android/settings/accessibility/CaptionMoreOptionsFragment.java b/src/com/android/settings/accessibility/CaptionMoreOptionsFragment.java index 8ac82e5f206..6aa69fa4075 100644 --- a/src/com/android/settings/accessibility/CaptionMoreOptionsFragment.java +++ b/src/com/android/settings/accessibility/CaptionMoreOptionsFragment.java @@ -26,18 +26,19 @@ import android.view.accessibility.CaptioningManager; import androidx.preference.Preference; import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; /** Settings fragment containing more options of captioning properties. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class CaptionMoreOptionsFragment extends SettingsPreferenceFragment +public class CaptionMoreOptionsFragment extends DashboardFragment implements Preference.OnPreferenceChangeListener { + + private static final String TAG = "CaptionMoreOptionsFragment"; private static final String PREF_LOCALE = "captioning_locale"; private CaptioningManager mCaptioningManager; - private LocalePreference mLocale; @Override @@ -46,17 +47,26 @@ public class CaptionMoreOptionsFragment extends SettingsPreferenceFragment } @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + super.onCreatePreferences(savedInstanceState, rootKey); mCaptioningManager = (CaptioningManager) getSystemService(Context.CAPTIONING_SERVICE); - addPreferencesFromResource(R.xml.captioning_more_options); initializeAllPreferences(); updateAllPreferences(); installUpdateListeners(); } + @Override + protected int getPreferenceScreenResId() { + return R.xml.captioning_more_options; + } + + @Override + protected String getLogTag() { + return TAG; + } + private void initializeAllPreferences() { mLocale = (LocalePreference) findPreference(PREF_LOCALE); } diff --git a/src/com/android/settings/accessibility/CaptionPropertiesFragment.java b/src/com/android/settings/accessibility/CaptionPropertiesFragment.java index 01458283907..bcdba11e7d3 100644 --- a/src/com/android/settings/accessibility/CaptionPropertiesFragment.java +++ b/src/com/android/settings/accessibility/CaptionPropertiesFragment.java @@ -28,7 +28,7 @@ import androidx.preference.Preference; import androidx.preference.Preference.OnPreferenceChangeListener; import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.widget.SettingsMainSwitchPreference; import com.android.settingslib.search.SearchIndexable; @@ -41,8 +41,10 @@ import java.util.List; /** Settings fragment containing captioning properties. */ @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) -public class CaptionPropertiesFragment extends SettingsPreferenceFragment +public class CaptionPropertiesFragment extends DashboardFragment implements OnPreferenceChangeListener, OnMainSwitchChangeListener { + + private static final String TAG = "CaptionPropertiesFragment"; private static final String PREF_SWITCH = "captioning_preference_switch"; private static final String PREF_TEXT = "captioning_caption_appearance"; private static final String PREF_MORE = "captioning_more_options"; @@ -62,12 +64,11 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment } @Override - public void onCreate(Bundle icicle) { - super.onCreate(icicle); + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + super.onCreatePreferences(savedInstanceState, rootKey); mCaptioningManager = (CaptioningManager) getSystemService(Context.CAPTIONING_SERVICE); - addPreferencesFromResource(R.xml.captioning_settings); initializeAllPreferences(); installUpdateListeners(); initFontSizeValuesArray(); @@ -79,6 +80,16 @@ public class CaptionPropertiesFragment extends SettingsPreferenceFragment updateAllPreferences(); } + @Override + protected int getPreferenceScreenResId() { + return R.xml.captioning_settings; + } + + @Override + protected String getLogTag() { + return TAG; + } + private void initializeAllPreferences() { mSwitch = (SettingsMainSwitchPreference) findPreference(PREF_SWITCH); mTextAppearance = (Preference) findPreference(PREF_TEXT); diff --git a/src/com/android/settings/accessibility/ToggleAutoclickFooterPreferenceController.java b/src/com/android/settings/accessibility/ToggleAutoclickFooterPreferenceController.java new file mode 100644 index 00000000000..014fc361bbc --- /dev/null +++ b/src/com/android/settings/accessibility/ToggleAutoclickFooterPreferenceController.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2021 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 android.content.Context; + +import com.android.settings.R; + +/** + * Preference controller for accessibility autoclick footer. + */ +public class ToggleAutoclickFooterPreferenceController extends + AccessibilityFooterPreferenceController { + + public ToggleAutoclickFooterPreferenceController(Context context, String key) { + super(context, key); + } + + @Override + protected String getLabelName() { + return mContext.getString(R.string.accessibility_autoclick_preference_title); + } +} diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java index c12884b04a5..7ff5e9f908b 100644 --- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java @@ -107,7 +107,7 @@ public final class ToggleDaltonizerPreferenceFragment extends ToggleFeaturePrefe lists.add(KEY_PREVIEW); lists.add(KEY_CATEGORY_MODE); lists.add(KEY_GENERAL_CATEGORY); - lists.add(KEY_INTRODUCTION_CATEGORY); + lists.add(KEY_HTML_DESCRIPTION_PREFERENCE); return lists; } diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index be6b1417b68..062bb73feff 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -54,7 +54,6 @@ import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; import com.android.settings.widget.SettingsMainSwitchBar; import com.android.settings.widget.SettingsMainSwitchPreference; import com.android.settingslib.accessibility.AccessibilityUtils; -import com.android.settingslib.widget.FooterPreference; import com.android.settingslib.widget.OnMainSwitchChangeListener; import java.lang.annotation.Retention; @@ -87,7 +86,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference private static final String DRAWABLE_FOLDER = "drawable"; protected static final String KEY_USE_SERVICE_PREFERENCE = "use_service"; protected static final String KEY_GENERAL_CATEGORY = "general_categories"; - protected static final String KEY_INTRODUCTION_CATEGORY = "introduction_categories"; + protected static final String KEY_HTML_DESCRIPTION_PREFERENCE = "html_description"; private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type"; protected static final String KEY_ANIMATED_IMAGE = "animated_image"; @@ -383,7 +382,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference lists.add(KEY_USE_SERVICE_PREFERENCE); lists.add(KEY_ANIMATED_IMAGE); lists.add(KEY_GENERAL_CATEGORY); - lists.add(KEY_INTRODUCTION_CATEGORY); + lists.add(KEY_HTML_DESCRIPTION_PREFERENCE); return lists; } @@ -495,44 +494,57 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference generalCategory.addPreference(mSettingsPreference); } - private void initIntroductionCategory() { - final PreferenceCategory introductionCategory = new PreferenceCategory(getPrefContext()); - final CharSequence title = - getString(R.string.accessibility_introduction_title, mPackageName); - introductionCategory.setKey(KEY_INTRODUCTION_CATEGORY); - introductionCategory.setTitle(title); - - getPreferenceScreen().addPreference(introductionCategory); - } - private void initHtmlTextPreference() { if (TextUtils.isEmpty(mHtmlDescription)) { return; } + final PreferenceScreen screen = getPreferenceScreen(); + final CharSequence htmlDescription = Html.fromHtml(mHtmlDescription.toString(), + Html.FROM_HTML_MODE_COMPACT, mImageGetter, /* tagHandler= */ null); + final String iconContentDescription = + getString(R.string.accessibility_introduction_title, mPackageName); - initIntroductionCategory(); - - final HtmlTextPreference htmlTextPreference = new HtmlTextPreference(getPrefContext()); - htmlTextPreference.setSummary(mHtmlDescription); - htmlTextPreference.setImageGetter(mImageGetter); - htmlTextPreference.setSelectable(false); - - final PreferenceCategory introductionCategory = findPreference(KEY_INTRODUCTION_CATEGORY); - introductionCategory.addPreference(htmlTextPreference); + final AccessibilityFooterPreference htmlFooterPreference = + new AccessibilityFooterPreference(screen.getContext()); + htmlFooterPreference.setKey(KEY_HTML_DESCRIPTION_PREFERENCE); + htmlFooterPreference.setSummary(htmlDescription); + htmlFooterPreference.setLinkEnabled(false); + htmlFooterPreference.setIconContentDescription(iconContentDescription); + screen.addPreference(htmlFooterPreference); } private void initFooterPreference() { if (!TextUtils.isEmpty(mDescription)) { - createFooterPreference(mDescription); + createFooterPreference(getPreferenceScreen(), mDescription, + getString(R.string.accessibility_introduction_title, mPackageName)); } if (TextUtils.isEmpty(mHtmlDescription) && TextUtils.isEmpty(mDescription)) { final CharSequence defaultDescription = getText(R.string.accessibility_service_default_description); - createFooterPreference(defaultDescription); + createFooterPreference(getPreferenceScreen(), defaultDescription, + getString(R.string.accessibility_introduction_title, mPackageName)); } } + + /** + * Creates {@link AccessibilityFooterPreference} and append into {@link PreferenceScreen} + * + * @param screen The preference screen to add the footer preference + * @param summary The summary of the preference summary. + * @param iconContentDescription The content description of icon in the footer. + */ + @VisibleForTesting + void createFooterPreference(PreferenceScreen screen, CharSequence summary, + String iconContentDescription) { + final AccessibilityFooterPreference footerPreference = + new AccessibilityFooterPreference(screen.getContext()); + footerPreference.setSummary(summary); + footerPreference.setIconContentDescription(iconContentDescription); + screen.addPreference(footerPreference); + } + @VisibleForTesting void setupEditShortcutDialog(Dialog dialog) { final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut); @@ -707,12 +719,6 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference showDialog(DialogEnums.EDIT_SHORTCUT); } - private void createFooterPreference(CharSequence title) { - final PreferenceScreen preferenceScreen = getPreferenceScreen(); - preferenceScreen.addPreference(new FooterPreference.Builder(getActivity()).setTitle( - title).build()); - } - /** * Setups a configurable default if the setting has never been set. */ diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..47914d83669 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFooterPreferenceControllerTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 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.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link AccessibilityButtonFooterPreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class AccessibilityButtonFooterPreferenceControllerTest { + + private static final String TEST_KEY = "test_key"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private PreferenceScreen mScreen; + private AccessibilityButtonFooterPreferenceController mController; + + @Before + public void setUp() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); + final AccessibilityFooterPreference footerPreference = + new AccessibilityFooterPreference(mContext); + footerPreference.setKey(TEST_KEY); + mScreen.addPreference(footerPreference); + mController = new AccessibilityButtonFooterPreferenceController(mContext, TEST_KEY); + } + + @Test + public void onPreferenceChange_shouldSetCorrectIconContentDescription() { + mController.displayPreference(mScreen); + + final AccessibilityFooterPreference footerPreference = mScreen.findPreference(TEST_KEY); + final String packageName = mContext.getString(R.string.accessibility_button_title); + final String iconContentDescription = mContext.getString( + R.string.accessibility_introduction_title, + packageName); + assertThat(footerPreference.getIconContentDescription()).isEqualTo(iconContentDescription); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityControlTimeoutFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityControlTimeoutFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..2f7a16f8199 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityControlTimeoutFooterPreferenceControllerTest.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 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.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link AccessibilityControlTimeoutFooterPreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class AccessibilityControlTimeoutFooterPreferenceControllerTest { + + private static final String TEST_KEY = "test_key"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private PreferenceScreen mScreen; + private AccessibilityControlTimeoutFooterPreferenceController mController; + + @Before + public void setUp() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); + final AccessibilityFooterPreference footerPreference = + new AccessibilityFooterPreference(mContext); + footerPreference.setKey(TEST_KEY); + mScreen.addPreference(footerPreference); + mController = new AccessibilityControlTimeoutFooterPreferenceController(mContext, TEST_KEY); + } + + @Test + public void onPreferenceChange_shouldSetCorrectIconContentDescription() { + mController.displayPreference(mScreen); + + final AccessibilityFooterPreference footerPreference = + mScreen.findPreference(TEST_KEY); + final String packageName = + mContext.getString(R.string.accessibility_setting_item_control_timeout_title); + final String iconContentDescription = mContext.getString( + R.string.accessibility_introduction_title, + packageName); + assertThat(footerPreference.getIconContentDescription()).isEqualTo(iconContentDescription); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityFooterPreferenceTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityFooterPreferenceTest.java new file mode 100644 index 00000000000..1d7ee4041ae --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityFooterPreferenceTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2019 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.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.preference.PreferenceViewHolder; + +import com.android.settingslib.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +/** Tests for {@link AccessibilityFooterPreference} */ +@RunWith(RobolectricTestRunner.class) +public final class AccessibilityFooterPreferenceTest { + + private static final String DEFAULT_SUMMARY = "default summary"; + private static final String DEFAULT_DESCRIPTION = "default description"; + + private AccessibilityFooterPreference mAccessibilityFooterPreference; + private PreferenceViewHolder mPreferenceViewHolder; + + @Before + public void setUp() { + final Context context = RuntimeEnvironment.application; + mAccessibilityFooterPreference = new AccessibilityFooterPreference(context); + + final LayoutInflater inflater = LayoutInflater.from(context); + final View view = + inflater.inflate(R.layout.preference_footer, null); + mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(view); + } + + @Test + public void onBindViewHolder_initTextConfig_parseTextAndFocusable() { + mAccessibilityFooterPreference.setSummary(DEFAULT_SUMMARY); + + mAccessibilityFooterPreference.onBindViewHolder(mPreferenceViewHolder); + + final TextView summaryView = (TextView) mPreferenceViewHolder.findViewById( + android.R.id.title); + assertThat(summaryView.getText().toString()).isEqualTo(DEFAULT_SUMMARY); + assertThat(summaryView.isFocusable()).isEqualTo(true); + } + + @Test + public void onBindViewHolder_initTextConfigAndAccessibleIcon_groupContentForAccessible() { + mAccessibilityFooterPreference.setSummary(DEFAULT_SUMMARY); + mAccessibilityFooterPreference.setIconContentDescription(DEFAULT_DESCRIPTION); + + mAccessibilityFooterPreference.onBindViewHolder(mPreferenceViewHolder); + + final TextView summaryView = (TextView) mPreferenceViewHolder.findViewById( + android.R.id.title); + assertThat(summaryView.getText().toString()).isEqualTo(DEFAULT_SUMMARY); + assertThat(summaryView.isFocusable()).isEqualTo(false); + final LinearLayout infoFrame = (LinearLayout) mPreferenceViewHolder.findViewById( + R.id.icon_frame); + assertThat(infoFrame.getContentDescription()).isEqualTo(DEFAULT_DESCRIPTION); + assertThat(infoFrame.isFocusable()).isEqualTo(false); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/CaptionFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/CaptionFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..b17dfc6c24e --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/CaptionFooterPreferenceControllerTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2021 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.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link CaptionFooterPreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class CaptionFooterPreferenceControllerTest { + + private static final String TEST_KEY = "test_key"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private PreferenceScreen mScreen; + private CaptionFooterPreferenceController mController; + + @Before + public void setUp() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); + final AccessibilityFooterPreference footerPreference = + new AccessibilityFooterPreference(mContext); + footerPreference.setKey(TEST_KEY); + mScreen.addPreference(footerPreference); + mController = new CaptionFooterPreferenceController(mContext, TEST_KEY); + } + + @Test + public void onPreferenceChange_shouldSetCorrectIconContentDescription() { + mController.displayPreference(mScreen); + + final AccessibilityFooterPreference footerPreference = mScreen.findPreference(TEST_KEY); + final String packageName = mContext.getString(R.string.accessibility_captioning_title); + final String iconContentDescription = mContext.getString( + R.string.accessibility_introduction_title, + packageName); + assertThat(footerPreference.getIconContentDescription()).isEqualTo(iconContentDescription); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickFooterPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickFooterPreferenceControllerTest.java new file mode 100644 index 00000000000..c94d62b663c --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickFooterPreferenceControllerTest.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2021 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.google.common.truth.Truth.assertThat; + +import android.content.Context; + +import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link ToggleAutoclickFooterPreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class ToggleAutoclickFooterPreferenceControllerTest { + + private static final String TEST_KEY = "test_key"; + private final Context mContext = ApplicationProvider.getApplicationContext(); + private PreferenceScreen mScreen; + private ToggleAutoclickFooterPreferenceController mController; + + @Before + public void setUp() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + mScreen = preferenceManager.createPreferenceScreen(mContext); + final AccessibilityFooterPreference footerPreference = + new AccessibilityFooterPreference(mContext); + footerPreference.setKey(TEST_KEY); + mScreen.addPreference(footerPreference); + mController = new ToggleAutoclickFooterPreferenceController(mContext, TEST_KEY); + } + + @Test + public void onPreferenceChange_shouldSetCorrectIconContentDescription() { + mController.displayPreference(mScreen); + + final AccessibilityFooterPreference footerPreference = mScreen.findPreference(TEST_KEY); + final String packageName = mContext.getString( + R.string.accessibility_autoclick_preference_title); + final String iconContentDescription = mContext.getString( + R.string.accessibility_introduction_title, + packageName); + assertThat(footerPreference.getIconContentDescription()).isEqualTo(iconContentDescription); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java index 6c62f192b6e..4b378c0efab 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 androidx.annotation.XmlRes; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.FragmentActivity; import androidx.preference.PreferenceManager; +import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; @@ -48,6 +49,7 @@ import com.android.settings.testutils.shadow.ShadowFragment; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Answers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -63,6 +65,8 @@ public class ToggleFeaturePreferenceFragmentTest { private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName( PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME); private static final String PLACEHOLDER_DIALOG_TITLE = "title"; + private static final String DEFAULT_SUMMARY = "default summary"; + private static final String DEFAULT_DESCRIPTION = "default description"; private static final String SOFTWARE_SHORTCUT_KEY = Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS; @@ -70,9 +74,10 @@ public class ToggleFeaturePreferenceFragmentTest { Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE; private TestToggleFeaturePreferenceFragment mFragment; + private PreferenceScreen mScreen; private Context mContext = ApplicationProvider.getApplicationContext(); - @Mock + @Mock(answer = Answers.RETURNS_DEEP_STUBS) private PreferenceManager mPreferenceManager; @Before @@ -83,7 +88,9 @@ public class ToggleFeaturePreferenceFragmentTest { when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager); when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext); when(mFragment.getContext()).thenReturn(mContext); - doReturn(null).when(mFragment).getPreferenceScreen(); + mScreen = spy(new PreferenceScreen(mContext, null)); + when(mScreen.getPreferenceManager()).thenReturn(mPreferenceManager); + doReturn(mScreen).when(mFragment).getPreferenceScreen(); } @Test @@ -195,6 +202,21 @@ public class ToggleFeaturePreferenceFragmentTest { assertThat(expectedType).isEqualTo(UserShortcutType.SOFTWARE | UserShortcutType.HARDWARE); } + @Test + public void createFooterPreference_shouldSetAsExpectedValue() { + mFragment.createFooterPreference(mFragment.getPreferenceScreen(), + DEFAULT_SUMMARY, DEFAULT_DESCRIPTION); + + AccessibilityFooterPreference accessibilityFooterPreference = + (AccessibilityFooterPreference) mFragment.getPreferenceScreen().getPreference( + mFragment.getPreferenceScreen().getPreferenceCount() - 1); + assertThat(accessibilityFooterPreference.getSummary()).isEqualTo(DEFAULT_SUMMARY); + assertThat(accessibilityFooterPreference.getIconContentDescription()).isEqualTo( + DEFAULT_DESCRIPTION); + assertThat(accessibilityFooterPreference.isSelectable()).isEqualTo(true); + assertThat(accessibilityFooterPreference.getOrder()).isEqualTo(Integer.MAX_VALUE - 1); + } + private void putStringIntoSettings(String key, String componentName) { Settings.Secure.putString(mContext.getContentResolver(), key, componentName); }