Merge changes I502e52f6,Iabf58566,Ida773967,Ic6c48861,If9e5cc6e, ...

* changes:
  New feature “Text and reading options” for SetupWizard, Wallpaper, and Settings (15/n).
  New feature “Text and reading options” for SetupWizard, Wallpaper, and Settings (14/n).
  New feature “Text and reading options” for SetupWizard, Wallpaper, and Settings (13/n).
  New feature “Text and reading options” for SetupWizard, Wallpaper, and Settings (12/n).
  New feature “Text and reading options” for SetupWizard, Wallpaper, and Settings (11/n).
  New feature “Text and reading options” for SetupWizard, Wallpaper, and Settings (10/n).
This commit is contained in:
PETER LIANG
2022-02-11 13:42:55 +00:00
committed by Android (Google) Code Review
23 changed files with 1262 additions and 14 deletions

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:shape="rectangle">
<corners android:radius="100dp" />
<solid android:color="?androidprv:attr/colorAccentPrimary" />
</shape>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart">
<Button
android:id="@+id/reset_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/accessibility_text_reading_reset_button_background"
android:paddingHorizontal="24dp"
android:paddingVertical="14dp"
android:text="@string/accessibility_text_reading_reset_button_title"
android:textAppearance="?android:attr/textAppearanceMedium" />
</FrameLayout>

View File

@@ -5236,6 +5236,8 @@
<string name="accessibility_text_reading_preview_mail_from">From: bill@email.com</string> <string name="accessibility_text_reading_preview_mail_from">From: bill@email.com</string>
<!-- Content for the mail content of the accessibility text reading preview. [CHAR LIMIT=NONE] --> <!-- Content for the mail content of the accessibility text reading preview. [CHAR LIMIT=NONE] -->
<string name="accessibility_text_reading_preview_mail_content">Good morning! Following up on our last conversation, Id like to check in on the progress of your time machine development plan. Will you be able to have a prototype ready to demo at E3 this year?</string> <string name="accessibility_text_reading_preview_mail_content">Good morning! Following up on our last conversation, Id like to check in on the progress of your time machine development plan. Will you be able to have a prototype ready to demo at E3 this year?</string>
<!-- Title for the reset button of the accessibility text reading page to reset all preferences state. [CHAR LIMIT=NONE] -->
<string name="accessibility_text_reading_reset_button_title">Reset</string>
<!-- Title for the footer text to explain what option accessibility service does. [CHAR LIMIT=35] --> <!-- Title for the footer text to explain what option accessibility service does. [CHAR LIMIT=35] -->
<string name="accessibility_screen_option">Options</string> <string name="accessibility_screen_option">Options</string>
<!-- Summary for the accessibility preference to enable screen magnification. [CHAR LIMIT=25] --> <!-- Summary for the accessibility preference to enable screen magnification. [CHAR LIMIT=25] -->

View File

@@ -21,16 +21,44 @@
android:persistent="false" android:persistent="false"
android:title="@string/accessibility_text_reading_options_title"> android:title="@string/accessibility_text_reading_options_title">
<com.android.settings.accessibility.TextReadingPreviewPreference
android:key="preview"
android:selectable="false"/>
<com.android.settings.widget.LabeledSeekBarPreference
android:key="font_size"
android:selectable="false"
android:summary="@string/short_summary_font_size"
android:title="@string/title_font_size"
settings:iconEnd="@drawable/ic_add_24dp"
settings:iconEndContentDescription="@string/font_size_make_larger_desc"
settings:iconStart="@drawable/ic_remove_24dp"
settings:iconStartContentDescription="@string/font_size_make_smaller_desc"/>
<com.android.settings.widget.LabeledSeekBarPreference
android:key="display_size"
android:selectable="false"
android:summary="@string/screen_zoom_short_summary"
android:title="@string/screen_zoom_title"
settings:iconEnd="@drawable/ic_add_24dp"
settings:iconEndContentDescription="@string/screen_zoom_make_larger_desc"
settings:iconStart="@drawable/ic_remove_24dp"
settings:iconStartContentDescription="@string/screen_zoom_make_smaller_desc"/>
<SwitchPreference <SwitchPreference
android:key="toggle_force_bold_text" android:key="toggle_force_bold_text"
android:persistent="false" android:persistent="false"
android:title="@string/force_bold_text" android:title="@string/force_bold_text"
settings:keywords="@string/keywords_bold_text" settings:keywords="@string/keywords_bold_text" />
settings:controller="com.android.settings.accessibility.FontWeightAdjustmentPreferenceController"/>
<SwitchPreference <SwitchPreference
android:key="toggle_high_text_contrast_preference" android:key="toggle_high_text_contrast_preference"
android:persistent="false" android:persistent="false"
android:title="@string/accessibility_toggle_high_text_contrast_preference_title" android:title="@string/accessibility_toggle_high_text_contrast_preference_title" />
settings:controller="com.android.settings.accessibility.HighTextContrastPreferenceController"/>
<com.android.settingslib.widget.LayoutPreference
android:key="reset"
android:layout="@layout/accessibility_text_reading_reset_button"
android:persistent="false"
android:selectable="false" />
</PreferenceScreen> </PreferenceScreen>

View File

@@ -0,0 +1,65 @@
/*
* 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 android.content.Context;
import android.content.res.Resources;
import android.view.Display;
import com.android.settingslib.display.DisplayDensityConfiguration;
import com.android.settingslib.display.DisplayDensityUtils;
import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Collectors;
/**
* Data class for storing the configurations related to the display size.
*/
class DisplaySizeData extends PreviewSizeData<Integer> {
DisplaySizeData(Context context) {
super(context);
final DisplayDensityUtils density = new DisplayDensityUtils(getContext());
final int initialIndex = density.getCurrentIndex();
if (initialIndex < 0) {
// Failed to obtain default density, which means we failed to
// connect to the window manager service. Just use the current
// density and don't let the user change anything.
final Resources resources = getContext().getResources();
final int densityDpi = resources.getDisplayMetrics().densityDpi;
setDefaultValue(densityDpi);
setInitialIndex(0);
setValues(Collections.singletonList(densityDpi));
} else {
setDefaultValue(density.getDefaultDensity());
setInitialIndex(initialIndex);
setValues(Arrays.stream(density.getValues()).boxed().collect(Collectors.toList()));
}
}
@Override
void commit(int currentProgress) {
final int densityDpi = getValues().get(currentProgress);
if (densityDpi == getDefaultValue()) {
DisplayDensityConfiguration.clearForcedDisplayDensity(Display.DEFAULT_DISPLAY);
} else {
DisplayDensityConfiguration.setForcedDisplayDensity(Display.DEFAULT_DISPLAY,
densityDpi);
}
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.display.ToggleFontSizePreferenceFragment.fontSizeValueToIndex;
import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.provider.Settings;
import com.android.settings.R;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Data class for storing the configurations related to the font size.
*/
final class FontSizeData extends PreviewSizeData<Float> {
private static final float FONT_SCALE_DEF_VALUE = 1.0f;
FontSizeData(Context context) {
super(context);
final Resources resources = getContext().getResources();
final ContentResolver resolver = getContext().getContentResolver();
final List<String> strEntryValues =
Arrays.asList(resources.getStringArray(R.array.entryvalues_font_size));
setDefaultValue(FONT_SCALE_DEF_VALUE);
final float currentScale =
Settings.System.getFloat(resolver, Settings.System.FONT_SCALE, getDefaultValue());
setInitialIndex(fontSizeValueToIndex(currentScale, strEntryValues.toArray(new String[0])));
setValues(strEntryValues.stream().map(Float::valueOf).collect(Collectors.toList()));
}
@Override
void commit(int currentProgress) {
final ContentResolver resolver = getContext().getContentResolver();
Settings.System.putFloat(resolver, Settings.System.FONT_SCALE,
getValues().get(currentProgress));
}
}

View File

@@ -24,7 +24,8 @@ import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
/** PreferenceController for displaying all text in bold. */ /** PreferenceController for displaying all text in bold. */
public class FontWeightAdjustmentPreferenceController extends TogglePreferenceController { public class FontWeightAdjustmentPreferenceController extends TogglePreferenceController implements
TextReadingResetController.ResetStateListener {
static final int BOLD_TEXT_ADJUSTMENT = static final int BOLD_TEXT_ADJUSTMENT =
FontStyle.FONT_WEIGHT_BOLD - FontStyle.FONT_WEIGHT_NORMAL; FontStyle.FONT_WEIGHT_BOLD - FontStyle.FONT_WEIGHT_NORMAL;
@@ -53,4 +54,9 @@ public class FontWeightAdjustmentPreferenceController extends TogglePreferenceCo
public int getSliceHighlightMenuRes() { public int getSliceHighlightMenuRes() {
return R.string.menu_key_accessibility; return R.string.menu_key_accessibility;
} }
@Override
public void resetState() {
setChecked(false);
}
} }

View File

@@ -22,7 +22,11 @@ import android.provider.Settings;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController; import com.android.settings.core.TogglePreferenceController;
public class HighTextContrastPreferenceController extends TogglePreferenceController { /**
* PreferenceController for displaying all text in high contrast style.
*/
public class HighTextContrastPreferenceController extends TogglePreferenceController implements
TextReadingResetController.ResetStateListener {
public HighTextContrastPreferenceController(Context context, String preferenceKey) { public HighTextContrastPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey); super(context, preferenceKey);
@@ -49,4 +53,9 @@ public class HighTextContrastPreferenceController extends TogglePreferenceContro
public int getSliceHighlightMenuRes() { public int getSliceHighlightMenuRes() {
return R.string.menu_key_accessibility; return R.string.menu_key_accessibility;
} }
@Override
public void resetState() {
setChecked(false);
}
} }

View File

@@ -0,0 +1,71 @@
/*
* 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 android.content.Context;
import androidx.annotation.NonNull;
import java.util.List;
/**
* Abstract data class for storing and fetching the configurations related to the preview of the
* text and reading options.
*/
abstract class PreviewSizeData<T extends Number> {
private final Context mContext;
private int mInitialIndex;
private T mDefaultValue;
private List<T> mValues;
PreviewSizeData(@NonNull Context context) {
mContext = context;
}
Context getContext() {
return mContext;
}
List<T> getValues() {
return mValues;
}
void setValues(List<T> values) {
mValues = values;
}
T getDefaultValue() {
return mDefaultValue;
}
void setDefaultValue(T defaultValue) {
mDefaultValue = defaultValue;
}
int getInitialIndex() {
return mInitialIndex;
}
void setInitialIndex(int initialIndex) {
mInitialIndex = initialIndex;
}
/**
* Persists the selected size.
*/
abstract void commit(int currentProgress);
}

View File

@@ -0,0 +1,119 @@
/*
* 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 android.content.Context;
import android.widget.SeekBar;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.widget.LabeledSeekBarPreference;
/**
* The controller of {@link LabeledSeekBarPreference} that listens to display size and font size
* settings changes and updates preview size threshold smoothly.
*/
class PreviewSizeSeekBarController extends BasePreferenceController implements
TextReadingResetController.ResetStateListener {
private final PreviewSizeData<? extends Number> mSizeData;
private boolean mSeekByTouch;
private ProgressInteractionListener mInteractionListener;
private LabeledSeekBarPreference mSeekBarPreference;
private final SeekBar.OnSeekBarChangeListener mSeekBarChangeListener =
new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
mInteractionListener.notifyPreferenceChanged();
if (!mSeekByTouch && mInteractionListener != null) {
mInteractionListener.onProgressChanged();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mSeekByTouch = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mSeekByTouch = false;
if (mInteractionListener != null) {
mInteractionListener.onEndTrackingTouch();
}
}
};
PreviewSizeSeekBarController(Context context, String preferenceKey,
@NonNull PreviewSizeData<? extends Number> sizeData) {
super(context, preferenceKey);
mSizeData = sizeData;
}
void setInteractionListener(ProgressInteractionListener interactionListener) {
mInteractionListener = interactionListener;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final int dataSize = mSizeData.getValues().size();
final int initialIndex = mSizeData.getInitialIndex();
mSeekBarPreference = screen.findPreference(getPreferenceKey());
mSeekBarPreference.setMax(dataSize - 1);
mSeekBarPreference.setProgress(initialIndex);
mSeekBarPreference.setContinuousUpdates(true);
mSeekBarPreference.setOnSeekBarChangeListener(mSeekBarChangeListener);
}
@Override
public void resetState() {
final int defaultProgress = mSizeData.getValues().indexOf(mSizeData.getDefaultValue());
mSeekBarPreference.setProgress(defaultProgress);
}
/**
* Interface for callbacks when users interact with the seek bar.
*/
interface ProgressInteractionListener {
/**
* Called when the progress is changed.
*/
void notifyPreferenceChanged();
/**
* Called when the progress is changed without tracking touch.
*/
void onProgressChanged();
/**
* Called when the seek bar is end tracking.
*/
void onEndTrackingTouch();
}
}

View File

@@ -16,13 +16,21 @@
package com.android.settings.accessibility; package com.android.settings.accessibility;
import static com.android.settings.accessibility.TextReadingResetController.ResetStateListener;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.Context;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment; import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider; import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable; import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/** /**
* Accessibility settings for adjusting the system features which are related to the reading. For * Accessibility settings for adjusting the system features which are related to the reading. For
* example, bold text, high contrast text, display size, font size and so on. * example, bold text, high contrast text, display size, font size and so on.
@@ -30,6 +38,12 @@ import com.android.settingslib.search.SearchIndexable;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC) @SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class TextReadingPreferenceFragment extends DashboardFragment { public class TextReadingPreferenceFragment extends DashboardFragment {
private static final String TAG = "TextReadingPreferenceFragment"; private static final String TAG = "TextReadingPreferenceFragment";
private static final String FONT_SIZE_KEY = "font_size";
private static final String DISPLAY_SIZE_KEY = "display_size";
private static final String PREVIEW_KEY = "preview";
private static final String RESET_KEY = "reset";
private static final String BOLD_TEXT_KEY = "toggle_force_bold_text";
private static final String HIGHT_TEXT_CONTRAST_KEY = "toggle_high_text_contrast_preference";
@Override @Override
protected int getPreferenceScreenResId() { protected int getPreferenceScreenResId() {
@@ -46,6 +60,44 @@ public class TextReadingPreferenceFragment extends DashboardFragment {
return SettingsEnums.ACCESSIBILITY_TEXT_READING_OPTIONS; return SettingsEnums.ACCESSIBILITY_TEXT_READING_OPTIONS;
} }
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
final FontSizeData fontSizeData = new FontSizeData(context);
final DisplaySizeData displaySizeData = new DisplaySizeData(context);
final TextReadingPreviewController previewController = new TextReadingPreviewController(
context, PREVIEW_KEY, fontSizeData, displaySizeData);
controllers.add(previewController);
final PreviewSizeSeekBarController fontSizeController = new PreviewSizeSeekBarController(
context, FONT_SIZE_KEY, fontSizeData);
fontSizeController.setInteractionListener(previewController);
controllers.add(fontSizeController);
final PreviewSizeSeekBarController displaySizeController = new PreviewSizeSeekBarController(
context, DISPLAY_SIZE_KEY, displaySizeData);
displaySizeController.setInteractionListener(previewController);
controllers.add(displaySizeController);
final FontWeightAdjustmentPreferenceController fontWeightController =
new FontWeightAdjustmentPreferenceController(context, BOLD_TEXT_KEY);
controllers.add(fontWeightController);
final HighTextContrastPreferenceController highTextContrastController =
new HighTextContrastPreferenceController(context, HIGHT_TEXT_CONTRAST_KEY);
controllers.add(highTextContrastController);
final List<ResetStateListener> resetStateListeners =
controllers.stream().filter(c -> c instanceof ResetStateListener).map(
c -> (ResetStateListener) c).collect(Collectors.toList());
final TextReadingResetController resetController =
new TextReadingResetController(context, RESET_KEY, resetStateListeners);
controllers.add(resetController);
return controllers;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.accessibility_text_reading_options); new BaseSearchIndexProvider(R.xml.accessibility_text_reading_options);
} }

View File

@@ -0,0 +1,194 @@
/*
* 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 android.content.Context;
import android.content.res.Configuration;
import android.os.SystemClock;
import android.view.Choreographer;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.display.PreviewPagerAdapter;
import com.android.settings.widget.LabeledSeekBarPreference;
import java.util.Objects;
/**
* A {@link BasePreferenceController} for controlling the preview pager of the text and reading
* options.
*/
class TextReadingPreviewController extends BasePreferenceController implements
PreviewSizeSeekBarController.ProgressInteractionListener {
static final int[] PREVIEW_SAMPLE_RES_IDS = new int[]{
R.layout.accessibility_text_reading_preview_app_grid,
R.layout.screen_zoom_preview_1,
R.layout.accessibility_text_reading_preview_mail_content};
private static final String PREVIEW_KEY = "preview";
private static final String FONT_SIZE_KEY = "font_size";
private static final String DISPLAY_SIZE_KEY = "display_size";
private static final long MIN_COMMIT_INTERVAL_MS = 800;
private static final long CHANGE_BY_SEEKBAR_DELAY_MS = 100;
private static final long CHANGE_BY_BUTTON_DELAY_MS = 300;
private final FontSizeData mFontSizeData;
private final DisplaySizeData mDisplaySizeData;
private int mLastFontProgress;
private int mLastDisplayProgress;
private long mLastCommitTime;
private TextReadingPreviewPreference mPreviewPreference;
private LabeledSeekBarPreference mFontSizePreference;
private LabeledSeekBarPreference mDisplaySizePreference;
private final Choreographer.FrameCallback mCommit = f -> {
tryCommitFontSizeConfig();
tryCommitDisplaySizeConfig();
mLastCommitTime = SystemClock.elapsedRealtime();
};
TextReadingPreviewController(Context context, String preferenceKey,
@NonNull FontSizeData fontSizeData, @NonNull DisplaySizeData displaySizeData) {
super(context, preferenceKey);
mFontSizeData = fontSizeData;
mDisplaySizeData = displaySizeData;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mPreviewPreference = screen.findPreference(PREVIEW_KEY);
mFontSizePreference = screen.findPreference(FONT_SIZE_KEY);
mDisplaySizePreference = screen.findPreference(DISPLAY_SIZE_KEY);
Objects.requireNonNull(mFontSizePreference,
/* message= */ "Font size preference is null, the preview controller "
+ "couldn't get the info");
Objects.requireNonNull(mDisplaySizePreference,
/* message= */ "Display size preference is null, the preview controller"
+ " couldn't get the info");
mLastFontProgress = mFontSizePreference.getProgress();
mLastDisplayProgress = mDisplaySizePreference.getProgress();
final Configuration origConfig = mContext.getResources().getConfiguration();
final boolean isLayoutRtl =
origConfig.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL;
final PreviewPagerAdapter pagerAdapter = new PreviewPagerAdapter(mContext, isLayoutRtl,
PREVIEW_SAMPLE_RES_IDS, createConfig(origConfig));
mPreviewPreference.setPreviewAdapter(pagerAdapter);
pagerAdapter.setPreviewLayer(/* newLayerIndex= */ 0,
/* currentLayerIndex= */ 0,
/* currentFrameIndex= */ 0, /* animate= */ false);
}
@Override
public void notifyPreferenceChanged() {
final int displayDataSize = mDisplaySizeData.getValues().size();
final int fontSizeProgress = mFontSizePreference.getProgress();
final int displaySizeProgress = mDisplaySizePreference.getProgress();
// To be consistent with the
// {@link PreviewPagerAdapter#setPreviewLayer(int, int, int, boolean)} behavior,
// here also needs the same design. In addition, please also refer to
// the {@link #createConfig(Configuration)}.
final int pagerIndex = fontSizeProgress * displayDataSize + displaySizeProgress;
mPreviewPreference.notifyPreviewPagerChanged(pagerIndex);
}
@Override
public void onProgressChanged() {
postCommitDelayed(CHANGE_BY_BUTTON_DELAY_MS);
}
@Override
public void onEndTrackingTouch() {
postCommitDelayed(CHANGE_BY_SEEKBAR_DELAY_MS);
}
/**
* Avoids the flicker when switching to the previous or next level.
*
* <p><br>[Flickering problem steps] commit()-> snapshot in framework(old screenshot) ->
* app update the preview -> snapshot(old screen) fade out</p>
*
* <p><br>To prevent flickering problem, we make sure that we update the local preview
* first and then we do the commit later. </p>
*
* <p><br><b>Note:</b> It doesn't matter that we use
* Choreographer or main thread handler since the delay time is longer
* than 1 frame. Use Choreographer to let developer understand it's a
* window update.</p>
*
* @param commitDelayMs the interval time after a action.
*/
void postCommitDelayed(long commitDelayMs) {
if (SystemClock.elapsedRealtime() - mLastCommitTime < MIN_COMMIT_INTERVAL_MS) {
commitDelayMs += MIN_COMMIT_INTERVAL_MS;
}
final Choreographer choreographer = Choreographer.getInstance();
choreographer.removeFrameCallback(mCommit);
choreographer.postFrameCallbackDelayed(mCommit, commitDelayMs);
}
private void tryCommitFontSizeConfig() {
final int fontProgress = mFontSizePreference.getProgress();
if (fontProgress != mLastFontProgress) {
mFontSizeData.commit(fontProgress);
mLastFontProgress = fontProgress;
}
}
private void tryCommitDisplaySizeConfig() {
final int displayProgress = mDisplaySizePreference.getProgress();
if (displayProgress != mLastDisplayProgress) {
mDisplaySizeData.commit(displayProgress);
mLastDisplayProgress = displayProgress;
}
}
private Configuration[] createConfig(Configuration origConfig) {
final int fontDataSize = mFontSizeData.getValues().size();
final int displayDataSize = mDisplaySizeData.getValues().size();
final int totalNum = fontDataSize * displayDataSize;
final Configuration[] configurations = new Configuration[totalNum];
for (int i = 0; i < fontDataSize; ++i) {
for (int j = 0; j < displayDataSize; ++j) {
final Configuration config = new Configuration(origConfig);
config.fontScale = mFontSizeData.getValues().get(i);
config.densityDpi = mDisplaySizeData.getValues().get(j);
configurations[i * displayDataSize + j] = config;
}
}
return configurations;
}
}

View File

@@ -32,8 +32,9 @@ import com.android.settings.widget.DotsPageIndicator;
/** /**
* A {@link Preference} that could show the preview related to the text and reading options. * A {@link Preference} that could show the preview related to the text and reading options.
*/ */
final class TextReadingPreviewPreference extends Preference { public class TextReadingPreviewPreference extends Preference {
private int mCurrentItem; private int mCurrentItem;
private int mLastLayerIndex;
private PreviewPagerAdapter mPreviewAdapter; private PreviewPagerAdapter mPreviewAdapter;
TextReadingPreviewPreference(Context context) { TextReadingPreviewPreference(Context context) {
@@ -41,7 +42,7 @@ final class TextReadingPreviewPreference extends Preference {
init(); init();
} }
TextReadingPreviewPreference(Context context, AttributeSet attrs) { public TextReadingPreviewPreference(Context context, AttributeSet attrs) {
super(context, attrs); super(context, attrs);
init(); init();
} }
@@ -120,4 +121,16 @@ final class TextReadingPreviewPreference extends Preference {
private void init() { private void init() {
setLayoutResource(R.layout.accessibility_text_reading_preview); setLayoutResource(R.layout.accessibility_text_reading_preview);
} }
void notifyPreviewPagerChanged(int pagerIndex) {
Preconditions.checkNotNull(mPreviewAdapter,
"Preview adapter is null, you should init the preview adapter first");
if (pagerIndex != mLastLayerIndex) {
mPreviewAdapter.setPreviewLayer(pagerIndex, mLastLayerIndex, getCurrentItem(),
/* animate= */ false);
}
mLastLayerIndex = pagerIndex;
}
} }

View File

@@ -0,0 +1,66 @@
/*
* 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 android.content.Context;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.LayoutPreference;
import java.util.List;
/**
* The controller of the reset button in the text and reading options page.
*/
class TextReadingResetController extends BasePreferenceController {
private final List<ResetStateListener> mListeners;
TextReadingResetController(Context context, String preferenceKey,
@NonNull List<ResetStateListener> listeners) {
super(context, preferenceKey);
mListeners = listeners;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
final LayoutPreference layoutPreference = screen.findPreference(getPreferenceKey());
final View view = layoutPreference.findViewById(R.id.reset_button);
view.setOnClickListener(v -> mListeners.forEach(ResetStateListener::resetState));
}
/**
* Interface for resetting to default state.
*/
interface ResetStateListener {
/**
* Called when the reset button was clicked.
*/
void resetState();
}
}

View File

@@ -117,7 +117,15 @@ public class PreviewPagerAdapter extends PagerAdapter {
mAnimationEndAction = action; mAnimationEndAction = action;
} }
void setPreviewLayer(int newLayerIndex, int currentLayerIndex, int currentFrameIndex, /**
* Switches the sample layouts for the preview pager.
*
* @param newLayerIndex the new layer index
* @param currentLayerIndex the current layer index
* @param currentFrameIndex the current frame index
* @param animate whether to enable the animation
*/
public void setPreviewLayer(int newLayerIndex, int currentLayerIndex, int currentFrameIndex,
final boolean animate) { final boolean animate) {
for (FrameLayout previewFrame : mPreviewFrames) { for (FrameLayout previewFrame : mPreviewFrames) {
if (currentLayerIndex >= 0) { if (currentLayerIndex >= 0) {

View File

@@ -0,0 +1,54 @@
/*
* 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.google.common.truth.Truth.assertThat;
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/**
* Tests for {@link DisplaySizeData}.
*/
@RunWith(RobolectricTestRunner.class)
public class DisplaySizeDataTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
private DisplaySizeData mDisplaySizeData;
@Before
public void setUp() {
mDisplaySizeData = new DisplaySizeData(mContext);
}
@Ignore("Ignore it since a NPE is happened in ShadowWindowManagerGlobal. (Ref. b/214161063)")
@Test
public void commit_success() {
final int progress = 4;
mDisplaySizeData.commit(progress);
final float density = mContext.getResources().getDisplayMetrics().density;
assertThat(density).isEqualTo(mDisplaySizeData.getValues().get(progress));
}
}

View File

@@ -0,0 +1,55 @@
/*
* 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.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
/**
* Tests for {@link FontSizeData}.
*/
@RunWith(RobolectricTestRunner.class)
public class FontSizeDataTest {
private final Context mContext = ApplicationProvider.getApplicationContext();
private FontSizeData mFontSizeData;
@Before
public void setUp() {
mFontSizeData = new FontSizeData(mContext);
}
@Test
public void commit_success() {
final int progress = 3;
mFontSizeData.commit(progress);
final float currentScale =
Settings.System.getFloat(mContext.getContentResolver(), Settings.System.FONT_SCALE,
/* def= */ 1.0f);
assertThat(currentScale).isEqualTo(mFontSizeData.getValues().get(progress));
}
}

View File

@@ -0,0 +1,98 @@
/*
* 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.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.widget.LabeledSeekBarPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
/**
* Tests for {@link PreviewSizeSeekBarController}.
*/
@RunWith(RobolectricTestRunner.class)
public class PreviewSizeSeekBarControllerTest {
private static final String FONT_SIZE_KEY = "font_size";
private final Context mContext = ApplicationProvider.getApplicationContext();
private PreviewSizeSeekBarController mSeekBarController;
private FontSizeData mFontSizeData;
private LabeledSeekBarPreference mSeekBarPreference;
@Mock
private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mFontSizeData = new FontSizeData(mContext);
mSeekBarController =
new PreviewSizeSeekBarController(mContext, FONT_SIZE_KEY, mFontSizeData);
mSeekBarPreference = spy(new LabeledSeekBarPreference(mContext, /* attrs= */ null));
when(mPreferenceScreen.findPreference(anyString())).thenReturn(mSeekBarPreference);
}
@Test
public void initMax_matchResult() {
when(mPreferenceScreen.findPreference(anyString())).thenReturn(mSeekBarPreference);
mSeekBarController.displayPreference(mPreferenceScreen);
assertThat(mSeekBarPreference.getMax()).isEqualTo(
mFontSizeData.getValues().size() - 1);
}
@Test
public void initProgress_matchResult() {
when(mPreferenceScreen.findPreference(anyString())).thenReturn(mSeekBarPreference);
mSeekBarController.displayPreference(mPreferenceScreen);
verify(mSeekBarPreference).setProgress(mFontSizeData.getInitialIndex());
}
@Test
public void resetToDefaultState_matchResult() {
final int defaultProgress =
mFontSizeData.getValues().indexOf(mFontSizeData.getDefaultValue());
when(mPreferenceScreen.findPreference(anyString())).thenReturn(mSeekBarPreference);
mSeekBarController.displayPreference(mPreferenceScreen);
mSeekBarPreference.setProgress(defaultProgress + 1);
mSeekBarController.resetState();
assertThat(mSeekBarPreference.getProgress()).isEqualTo(defaultProgress);
}
}

View File

@@ -0,0 +1,119 @@
/*
* 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 org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.display.PreviewPagerAdapter;
import com.android.settings.widget.LabeledSeekBarPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowChoreographer;
import java.util.ArrayList;
import java.util.List;
/**
* Tests for {@link TextReadingPreviewController}.
*/
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowChoreographer.class)
public class TextReadingPreviewControllerTest {
private static final String PREVIEW_KEY = "preview";
private static final String FONT_SIZE_KEY = "font_size";
private static final String DISPLAY_SIZE_KEY = "display_size";
private final Context mContext = ApplicationProvider.getApplicationContext();
private TextReadingPreviewController mPreviewController;
private TextReadingPreviewPreference mPreviewPreference;
private LabeledSeekBarPreference mFontSizePreference;
private LabeledSeekBarPreference mDisplaySizePreference;
@Mock
private DisplaySizeData mDisplaySizeData;
@Mock
private PreferenceScreen mPreferenceScreen;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
final FontSizeData fontSizeData = new FontSizeData(mContext);
final List<Integer> displayData = createFakeDisplayData();
when(mDisplaySizeData.getValues()).thenReturn(displayData);
mPreviewPreference = spy(new TextReadingPreviewPreference(mContext, /* attr= */ null));
mPreviewController = new TextReadingPreviewController(mContext, PREVIEW_KEY, fontSizeData,
mDisplaySizeData);
mFontSizePreference = new LabeledSeekBarPreference(mContext, /* attr= */ null);
mDisplaySizePreference = new LabeledSeekBarPreference(mContext, /* attr= */ null);
}
@Test
public void initPreviewerAdapter_verifyAction() {
when(mPreferenceScreen.findPreference(PREVIEW_KEY)).thenReturn(mPreviewPreference);
when(mPreferenceScreen.findPreference(FONT_SIZE_KEY)).thenReturn(mFontSizePreference);
when(mPreferenceScreen.findPreference(DISPLAY_SIZE_KEY)).thenReturn(mDisplaySizePreference);
mPreviewController.displayPreference(mPreferenceScreen);
verify(mPreviewPreference).setPreviewAdapter(any(PreviewPagerAdapter.class));
}
@Test(expected = NullPointerException.class)
public void initPreviewerAdapterWithoutDisplaySizePreference_throwNPE() {
when(mPreferenceScreen.findPreference(PREVIEW_KEY)).thenReturn(mPreviewPreference);
when(mPreferenceScreen.findPreference(DISPLAY_SIZE_KEY)).thenReturn(mDisplaySizePreference);
mPreviewController.displayPreference(mPreferenceScreen);
verify(mPreviewPreference).setPreviewAdapter(any(PreviewPagerAdapter.class));
}
@Test(expected = NullPointerException.class)
public void initPreviewerAdapterWithoutFontSizePreference_throwNPE() {
when(mPreferenceScreen.findPreference(PREVIEW_KEY)).thenReturn(mPreviewPreference);
when(mPreferenceScreen.findPreference(FONT_SIZE_KEY)).thenReturn(mFontSizePreference);
mPreviewController.displayPreference(mPreferenceScreen);
verify(mPreviewPreference).setPreviewAdapter(any(PreviewPagerAdapter.class));
}
private List<Integer> createFakeDisplayData() {
final List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
return list;
}
}

View File

@@ -16,8 +16,16 @@
package com.android.settings.accessibility; package com.android.settings.accessibility;
import static com.android.settings.accessibility.TextReadingPreviewController.PREVIEW_SAMPLE_RES_IDS;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context; import android.content.Context;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@@ -50,12 +58,11 @@ public class TextReadingPreviewPreferenceTest {
@Before @Before
public void setUp() { public void setUp() {
final Context context = ApplicationProvider.getApplicationContext(); final Context context = ApplicationProvider.getApplicationContext();
final int[] sampleResIds = new int[]{1, 2, 3, 4, 5, 6}; final Configuration[] configurations = createConfigurations(PREVIEW_SAMPLE_RES_IDS.length);
final Configuration[] configurations = createConfigurations(6);
mTextReadingPreviewPreference = new TextReadingPreviewPreference(context); mTextReadingPreviewPreference = new TextReadingPreviewPreference(context);
mPreviewPagerAdapter = mPreviewPagerAdapter =
new PreviewPagerAdapter(context, /* isLayoutRtl= */ false, sampleResIds, spy(new PreviewPagerAdapter(context, /* isLayoutRtl= */ false,
configurations); PREVIEW_SAMPLE_RES_IDS, configurations));
final LayoutInflater inflater = LayoutInflater.from(context); final LayoutInflater inflater = LayoutInflater.from(context);
final View view = final View view =
inflater.inflate(mTextReadingPreviewPreference.getLayoutResource(), inflater.inflate(mTextReadingPreviewPreference.getLayoutResource(),
@@ -87,7 +94,7 @@ public class TextReadingPreviewPreferenceTest {
@Test @Test
public void setCurrentItem_success() { public void setCurrentItem_success() {
final int currentItem = 3; final int currentItem = 1;
mTextReadingPreviewPreference.setPreviewAdapter(mPreviewPagerAdapter); mTextReadingPreviewPreference.setPreviewAdapter(mPreviewPagerAdapter);
mTextReadingPreviewPreference.onBindViewHolder(mHolder); mTextReadingPreviewPreference.onBindViewHolder(mHolder);
@@ -104,6 +111,24 @@ public class TextReadingPreviewPreferenceTest {
mTextReadingPreviewPreference.setCurrentItem(currentItem); mTextReadingPreviewPreference.setCurrentItem(currentItem);
} }
@Test(expected = NullPointerException.class)
public void updatePagerWithoutPreviewAdapter_throwNPE() {
final int index = 1;
mTextReadingPreviewPreference.notifyPreviewPagerChanged(index);
}
@Test
public void notifyPreviewPager_setPreviewLayer() {
final int index = 2;
mTextReadingPreviewPreference.setPreviewAdapter(mPreviewPagerAdapter);
mTextReadingPreviewPreference.onBindViewHolder(mHolder);
mTextReadingPreviewPreference.notifyPreviewPagerChanged(index);
verify(mPreviewPagerAdapter).setPreviewLayer(eq(index), anyInt(), anyInt(), anyBoolean());
}
private static Configuration[] createConfigurations(int count) { private static Configuration[] createConfigurations(int count) {
final Configuration[] configurations = new Configuration[count]; final Configuration[] configurations = new Configuration[count];
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {

View File

@@ -0,0 +1,119 @@
/*
* 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.TextReadingResetController.ResetStateListener;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.view.View;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.widget.LayoutPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
/**
* Tests for {@link TextReadingResetController}.
*/
@RunWith(RobolectricTestRunner.class)
public class TextReadingResetControllerTest {
private static final String TEST_KEY = "test";
private static final String RESET_KEY = "reset";
private final Context mContext = ApplicationProvider.getApplicationContext();
private final View mResetView = new View(mContext);
private final List<ResetStateListener> mListeners = new ArrayList<>();
private TextReadingResetController mResetController;
private TestPreferenceController mPreferenceController;
@Mock
private PreferenceScreen mPreferenceScreen;
@Mock
private LayoutPreference mLayoutPreference;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mPreferenceController = new TestPreferenceController(mContext, TEST_KEY);
mListeners.add(mPreferenceController);
mResetController = new TextReadingResetController(mContext, RESET_KEY, mListeners);
}
@Test
public void setClickListener_success() {
setupResetButton();
mResetController.displayPreference(mPreferenceScreen);
assertThat(mResetView.hasOnClickListeners()).isTrue();
}
@Test
public void triggerResetState_success() {
setupResetButton();
mResetController.displayPreference(mPreferenceScreen);
mResetView.callOnClick();
assertThat(mPreferenceController.isReset()).isTrue();
}
private void setupResetButton() {
when(mPreferenceScreen.findPreference(RESET_KEY)).thenReturn(mLayoutPreference);
when(mLayoutPreference.findViewById(R.id.reset_button)).thenReturn(mResetView);
}
private static class TestPreferenceController extends BasePreferenceController implements
ResetStateListener {
private boolean mIsReset = false;
TestPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public void resetState() {
mIsReset = true;
}
@Override
public int getAvailabilityStatus() {
return AVAILABLE;
}
boolean isReset() {
return mIsReset;
}
}
}

View File

@@ -31,6 +31,9 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
/**
* Tests for {@link FontWeightAdjustmentPreferenceController}.
*/
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class FontWeightAdjustmentPreferenceControllerTest { public class FontWeightAdjustmentPreferenceControllerTest {
private static final int ON = FontWeightAdjustmentPreferenceController.BOLD_TEXT_ADJUSTMENT; private static final int ON = FontWeightAdjustmentPreferenceController.BOLD_TEXT_ADJUSTMENT;
@@ -91,4 +94,14 @@ public class FontWeightAdjustmentPreferenceControllerTest {
assertThat(Settings.Secure.getInt(mContext.getContentResolver(), assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.FONT_WEIGHT_ADJUSTMENT, OFF)).isEqualTo(OFF); Settings.Secure.FONT_WEIGHT_ADJUSTMENT, OFF)).isEqualTo(OFF);
} }
@Test
public void resetState_shouldDisableBoldText() {
mController.setChecked(true);
mController.resetState();
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.FONT_WEIGHT_ADJUSTMENT, OFF)).isEqualTo(OFF);
}
} }

View File

@@ -31,6 +31,9 @@ import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
/**
* Tests for {@link HighTextContrastPreferenceController}.
*/
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class HighTextContrastPreferenceControllerTest { public class HighTextContrastPreferenceControllerTest {
@@ -93,4 +96,14 @@ public class HighTextContrastPreferenceControllerTest {
assertThat(Settings.Secure.getInt(mContext.getContentResolver(), assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, UNKNOWN)).isEqualTo(OFF); Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, UNKNOWN)).isEqualTo(OFF);
} }
@Test
public void resetState_shouldDisableTextContrast() {
mController.setChecked(true);
mController.resetState();
assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, UNKNOWN)).isEqualTo(OFF);
}
} }