Merge "Extract the logic of MagnificationMode to the controller" into sc-dev

This commit is contained in:
Ryan Lin
2021-04-16 03:50:27 +00:00
committed by Android (Google) Code Review
8 changed files with 531 additions and 429 deletions

View File

@@ -47,13 +47,13 @@
android:orientation="vertical">
<Button
android:id="@+id/switch_shortcut_positive_button"
android:id="@+id/custom_positive_button"
style="@style/AccessibilityDialogButton"
android:gravity="center|end"
android:text="@string/accessibility_magnification_switch_shortcut_positive_button"/>
<Button
android:id="@+id/switch_shortcut_negative_button"
android:id="@+id/custom_negative_button"
style="@style/AccessibilityDialogButton"
android:gravity="center|end"
android:text="@string/accessibility_magnification_switch_shortcut_negative_button"/>

View File

@@ -118,18 +118,19 @@ public class AccessibilityEditDialogUtils {
*
* @param context A valid context
* @param dialogTitle The title of magnify edit shortcut dialog
* @param listener The listener to determine the action of magnify edit shortcut dialog
* @param positiveBtnListener The positive button listener
* @return A magnification edit shortcut dialog in Magnification
*/
public static Dialog showMagnificationSwitchShortcutDialog(Context context,
CharSequence dialogTitle, View.OnClickListener listener) {
public static Dialog createMagnificationSwitchShortcutDialog(Context context,
CharSequence dialogTitle, CustomButtonsClickListener positiveBtnListener) {
final View contentView = createSwitchShortcutDialogContentView(context);
final AlertDialog alertDialog = new AlertDialog.Builder(context)
.setView(createSwitchShortcutDialogContentView(context))
.setView(contentView)
.setTitle(dialogTitle)
.create();
alertDialog.show();
setEditShortcutButtonsListener(alertDialog, listener);
setScrollIndicators(alertDialog);
setCustomButtonsClickListener(alertDialog, contentView,
positiveBtnListener, /* negativeBtnListener= */ null);
setScrollIndicators(contentView);
return alertDialog;
}
@@ -169,16 +170,50 @@ public class AccessibilityEditDialogUtils {
View.SCROLL_INDICATOR_TOP | View.SCROLL_INDICATOR_BOTTOM);
}
private static void setEditShortcutButtonsListener(AlertDialog dialog,
View.OnClickListener listener) {
final View contentView = dialog.findViewById(R.id.container_layout);
final Button positiveButton = contentView.findViewById(
R.id.switch_shortcut_positive_button);
final Button negativeButton = contentView.findViewById(
R.id.switch_shortcut_negative_button);
positiveButton.setOnClickListener(listener);
negativeButton.setOnClickListener(v -> dialog.dismiss());
interface CustomButtonsClickListener {
void onClick(@CustomButton int which);
}
/**
* Annotation for customized dialog button type.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
CustomButton.POSITIVE,
CustomButton.NEGATIVE,
})
public @interface CustomButton {
int POSITIVE = 1;
int NEGATIVE = 2;
}
private static void setCustomButtonsClickListener(Dialog dialog, View contentView,
CustomButtonsClickListener positiveBtnListener,
CustomButtonsClickListener negativeBtnListener) {
final Button positiveButton = contentView.findViewById(
R.id.custom_positive_button);
final Button negativeButton = contentView.findViewById(
R.id.custom_negative_button);
if (positiveButton != null) {
positiveButton.setOnClickListener(v -> {
if (positiveBtnListener != null) {
positiveBtnListener.onClick(CustomButton.POSITIVE);
}
dialog.dismiss();
});
}
if (negativeButton != null) {
negativeButton.setOnClickListener(v -> {
if (negativeBtnListener != null) {
negativeBtnListener.onClick(CustomButton.NEGATIVE);
}
dialog.dismiss();
});
}
}
private static View createSwitchShortcutDialogContentView(Context context) {

View File

@@ -42,12 +42,14 @@ public final class MagnificationCapabilities {
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({
MagnificationMode.NONE,
MagnificationMode.FULLSCREEN,
MagnificationMode.WINDOW,
MagnificationMode.ALL,
})
public @interface MagnificationMode {
int NONE = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_NONE;
int FULLSCREEN = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN;
int WINDOW = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
int ALL = Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL;

View File

@@ -16,15 +16,85 @@
package com.android.settings.accessibility;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.settings.accessibility.AccessibilityEditDialogUtils.CustomButton;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import com.android.settings.core.BasePreferenceController;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnCreate;
import com.android.settingslib.core.lifecycle.events.OnSaveInstanceState;
/** Controller that shows the magnification area mode summary. */
public class MagnificationModePreferenceController extends BasePreferenceController {
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
/** Controller that shows the magnification area mode summary and the preference click behavior. */
public class MagnificationModePreferenceController extends BasePreferenceController implements
DialogCreatable, LifecycleObserver, OnCreate, OnSaveInstanceState {
private static final int DIALOG_ID_BASE = 10;
@VisibleForTesting
static final int DIALOG_MAGNIFICATION_MODE = DIALOG_ID_BASE + 1;
@VisibleForTesting
static final int DIALOG_MAGNIFICATION_SWITCH_SHORTCUT = DIALOG_ID_BASE + 2;
@VisibleForTesting
static final String EXTRA_MODE = "mode";
private static final String TAG = "MagnificationModePreferenceController";
private static final char COMPONENT_NAME_SEPARATOR = ':';
private MagnificationSettingsFragment mParentFragment;
// The magnification mode in the dialog.
private int mMode = MagnificationMode.NONE;
private Preference mModePreference;
@VisibleForTesting
ListView mMagnificationModesListView;
private final List<MagnificationModeInfo> mModeInfos = new ArrayList<>();
public MagnificationModePreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
initModeInfos();
}
private void initModeInfos() {
mModeInfos.add(new MagnificationModeInfo(mContext.getText(
R.string.accessibility_magnification_mode_dialog_option_full_screen), null,
R.drawable.ic_illustration_fullscreen, MagnificationMode.FULLSCREEN));
mModeInfos.add(new MagnificationModeInfo(
mContext.getText(R.string.accessibility_magnification_mode_dialog_option_window),
null, R.drawable.ic_illustration_window, MagnificationMode.WINDOW));
mModeInfos.add(new MagnificationModeInfo(
mContext.getText(R.string.accessibility_magnification_mode_dialog_option_switch),
mContext.getText(
R.string.accessibility_magnification_area_settings_mode_switch_summary),
R.drawable.ic_illustration_switch, MagnificationMode.ALL));
}
@Override
@@ -32,10 +102,180 @@ public class MagnificationModePreferenceController extends BasePreferenceControl
return AVAILABLE;
}
@Override
public CharSequence getSummary() {
final int capabilities = MagnificationCapabilities.getCapabilities(mContext);
return MagnificationCapabilities.getSummary(mContext, capabilities);
}
@Override
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null) {
mMode = savedInstanceState.getInt(EXTRA_MODE, MagnificationMode.NONE);
}
}
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
mModePreference = screen.findPreference(getPreferenceKey());
mModePreference.setOnPreferenceClickListener(preference -> {
mMode = MagnificationCapabilities.getCapabilities(mContext);
mParentFragment.showDialog(DIALOG_MAGNIFICATION_MODE);
return true;
});
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_MODE, mMode);
}
public void setParentFragment(MagnificationSettingsFragment parentFragment) {
mParentFragment = parentFragment;
}
@Override
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DIALOG_MAGNIFICATION_MODE:
return createMagnificationModeDialog();
case DIALOG_MAGNIFICATION_SWITCH_SHORTCUT:
return createMagnificationShortCutConfirmDialog();
}
return null;
}
@Override
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
case DIALOG_MAGNIFICATION_MODE:
return SettingsEnums.DIALOG_MAGNIFICATION_CAPABILITY;
case DIALOG_MAGNIFICATION_SWITCH_SHORTCUT:
return SettingsEnums.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT;
default:
return 0;
}
}
private Dialog createMagnificationModeDialog() {
mMagnificationModesListView = AccessibilityEditDialogUtils.createSingleChoiceListView(
mContext, mModeInfos, this::onMagnificationModeSelected);
final View headerView = LayoutInflater.from(mContext).inflate(
R.layout.accessibility_magnification_mode_header, mMagnificationModesListView,
false);
mMagnificationModesListView.addHeaderView(headerView, /* data= */ null, /* isSelectable= */
false);
mMagnificationModesListView.setItemChecked(computeSelectionIndex(), true);
final CharSequence title = mContext.getString(
R.string.accessibility_magnification_mode_dialog_title);
return AccessibilityEditDialogUtils.createCustomDialog(mContext, title,
mMagnificationModesListView, this::onMagnificationModeDialogPositiveButtonClicked);
}
private void onMagnificationModeDialogPositiveButtonClicked(DialogInterface dialogInterface,
int which) {
final int selectedIndex = mMagnificationModesListView.getCheckedItemPosition();
if (selectedIndex != AdapterView.INVALID_POSITION) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) mMagnificationModesListView.getItemAtPosition(
selectedIndex);
setMode(modeInfo.mMagnificationMode);
} else {
Log.w(TAG, "invalid index");
}
}
private void setMode(int mode) {
mMode = mode;
MagnificationCapabilities.setCapabilities(mContext, mMode);
mModePreference.setSummary(
MagnificationCapabilities.getSummary(mContext, mMode));
}
private void onMagnificationModeSelected(AdapterView<?> parent, View view, int position,
long id) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) mMagnificationModesListView.getItemAtPosition(
position);
if (modeInfo.mMagnificationMode == mMode) {
return;
}
mMode = modeInfo.mMagnificationMode;
if (isTripleTapEnabled(mContext) && mMode != MagnificationMode.FULLSCREEN) {
mParentFragment.showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
}
private int computeSelectionIndex() {
final int modesSize = mModeInfos.size();
for (int i = 0; i < modesSize; i++) {
if (mModeInfos.get(i).mMagnificationMode == mMode) {
return i + mMagnificationModesListView.getHeaderViewsCount();
}
}
Log.w(TAG, "computeSelectionIndex failed");
return 0;
}
@VisibleForTesting
static boolean isTripleTapEnabled(Context context) {
return Settings.Secure.getInt(context.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF) == ON;
}
private Dialog createMagnificationShortCutConfirmDialog() {
final String title = mContext.getString(
R.string.accessibility_magnification_switch_shortcut_title);
return AccessibilityEditDialogUtils.createMagnificationSwitchShortcutDialog(mContext, title,
this::onSwitchShortcutDialogButtonClicked);
}
@VisibleForTesting
void onSwitchShortcutDialogButtonClicked(@CustomButton int which) {
optOutMagnificationFromTripleTap();
//TODO(b/147990389): Merge this function into AccessibilityUtils after the format of
// magnification target is changed to ComponentName.
optInMagnificationToAccessibilityButton();
}
private void optOutMagnificationFromTripleTap() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF);
}
private void optInMagnificationToAccessibilityButton() {
final String targetKey = Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
final String targetString = Settings.Secure.getString(mContext.getContentResolver(),
targetKey);
if (targetString != null && targetString.contains(MAGNIFICATION_CONTROLLER_NAME)) {
return;
}
final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR));
if (!TextUtils.isEmpty(targetString)) {
joiner.add(targetString);
}
joiner.add(MAGNIFICATION_CONTROLLER_NAME);
Settings.Secure.putString(mContext.getContentResolver(), targetKey,
joiner.toString());
}
@VisibleForTesting
static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo {
@MagnificationMode
public final int mMagnificationMode;
MagnificationModeInfo(@NonNull CharSequence title, @Nullable CharSequence summary,
@DrawableRes int drawableId, @MagnificationMode int magnificationMode) {
super(title, summary, drawableId);
mMagnificationMode = magnificationMode;
}
}
}

View File

@@ -16,104 +16,46 @@
package com.android.settings.accessibility;
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import android.content.Context;
import com.android.settings.R;
import com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
import java.util.StringJoiner;
/** Settings page for magnification. */
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class MagnificationSettingsFragment extends DashboardFragment {
private static final String TAG = "MagnificationSettingsFragment";
private static final String PREF_KEY_MODE = "magnification_mode";
@VisibleForTesting
static final int DIALOG_MAGNIFICATION_CAPABILITY = 1;
@VisibleForTesting
static final int DIALOG_MAGNIFICATION_SWITCH_SHORTCUT = 2;
@VisibleForTesting
static final String EXTRA_CAPABILITY = "capability";
private static final int NONE = 0;
private static final char COMPONENT_NAME_SEPARATOR = ':';
private Preference mModePreference;
@VisibleForTesting
Dialog mDialog;
@VisibleForTesting
ListView mMagnificationModesListView;
private int mCapabilities = NONE;
private final List<MagnificationModeInfo> mModeInfos = new ArrayList<>();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mCapabilities = savedInstanceState.getInt(EXTRA_CAPABILITY, NONE);
}
if (mCapabilities == NONE) {
mCapabilities = MagnificationCapabilities.getCapabilities(getPrefContext());
}
initModeInfos();
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
initModePreference();
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putInt(EXTRA_CAPABILITY, mCapabilities);
super.onSaveInstanceState(outState);
}
private MagnificationModePreferenceController mMagnificationModePreferenceController;
@Override
public int getMetricsCategory() {
return SettingsEnums.ACCESSIBILITY_MAGNIFICATION_SETTINGS;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
mMagnificationModePreferenceController = use(MagnificationModePreferenceController.class);
mMagnificationModePreferenceController.setParentFragment(this);
}
@Override
protected void showDialog(int dialogId) {
super.showDialog(dialogId);
}
@Override
public int getDialogMetricsCategory(int dialogId) {
switch (dialogId) {
case DIALOG_MAGNIFICATION_CAPABILITY:
return SettingsEnums.DIALOG_MAGNIFICATION_CAPABILITY;
case DIALOG_MAGNIFICATION_SWITCH_SHORTCUT:
return SettingsEnums.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT;
default:
return 0;
if (mMagnificationModePreferenceController != null) {
return mMagnificationModePreferenceController.getDialogMetricsCategory(dialogId);
}
return 0;
}
@Override
@@ -128,155 +70,13 @@ public class MagnificationSettingsFragment extends DashboardFragment {
@Override
public Dialog onCreateDialog(int dialogId) {
final CharSequence title;
switch (dialogId) {
case DIALOG_MAGNIFICATION_CAPABILITY:
mDialog = createMagnificationModeDialog();
return mDialog;
case DIALOG_MAGNIFICATION_SWITCH_SHORTCUT:
title = getPrefContext().getString(
R.string.accessibility_magnification_switch_shortcut_title);
mDialog = AccessibilityEditDialogUtils.showMagnificationSwitchShortcutDialog(
getPrefContext(), title, this::onSwitchShortcutDialogPositiveButtonClicked);
return mDialog;
}
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
}
private Dialog createMagnificationModeDialog() {
mMagnificationModesListView = AccessibilityEditDialogUtils.createSingleChoiceListView(
getPrefContext(), mModeInfos, this::onMagnificationModeSelected);
final View headerView = LayoutInflater.from(getPrefContext()).inflate(
R.layout.accessibility_magnification_mode_header, mMagnificationModesListView,
false);
mMagnificationModesListView.addHeaderView(headerView, null, /* isSelectable= */false);
mMagnificationModesListView.setItemChecked(computeSelectedMagnificationModeIndex(), true);
final CharSequence title = getPrefContext().getString(
R.string.accessibility_magnification_mode_dialog_title);
return AccessibilityEditDialogUtils.createCustomDialog(getPrefContext(), title,
mMagnificationModesListView, this::onMagnificationModeDialogPositiveButtonClicked);
}
private int computeSelectedMagnificationModeIndex() {
final int size = mModeInfos.size();
for (int i = 0; i < size; i++) {
if (mModeInfos.get(i).mMagnificationMode == mCapabilities) {
return i + mMagnificationModesListView.getHeaderViewsCount();
if (mMagnificationModePreferenceController != null) {
final Dialog dialog = mMagnificationModePreferenceController.onCreateDialog(dialogId);
if (dialog != null) {
return dialog;
}
}
Log.w(TAG, "chosen mode" + mCapabilities + "is not in the list");
return 0;
}
private void onMagnificationModeSelected(AdapterView<?> parent, View view, int position,
long id) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) mMagnificationModesListView.getItemAtPosition(position);
if (modeInfo.mMagnificationMode == mCapabilities) {
return;
}
mCapabilities = modeInfo.mMagnificationMode;
if (isTripleTapEnabled() && mCapabilities != MagnificationMode.FULLSCREEN) {
showDialog(DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
}
private void onMagnificationModeDialogPositiveButtonClicked(DialogInterface dialogInterface,
int which) {
final int selectedIndex = mMagnificationModesListView.getCheckedItemPosition();
if (selectedIndex != AdapterView.INVALID_POSITION) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) mMagnificationModesListView.getItemAtPosition(
selectedIndex);
updateCapabilities(modeInfo.mMagnificationMode);
} else {
Log.w(TAG, "no checked item in the list");
}
}
private void updateCapabilities(int mode) {
mCapabilities = mode;
MagnificationCapabilities.setCapabilities(getPrefContext(), mCapabilities);
mModePreference.setSummary(
MagnificationCapabilities.getSummary(getPrefContext(), mCapabilities));
}
private void initModeInfos() {
mModeInfos.clear();
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_full_screen), null,
R.drawable.ic_illustration_fullscreen, MagnificationMode.FULLSCREEN));
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_window), null,
R.drawable.ic_illustration_window, MagnificationMode.WINDOW));
mModeInfos.add(new MagnificationModeInfo(getPrefContext().getText(
R.string.accessibility_magnification_mode_dialog_option_switch),
getPrefContext().getText(
R.string.accessibility_magnification_area_settings_mode_switch_summary),
R.drawable.ic_illustration_switch, MagnificationMode.ALL));
}
@VisibleForTesting
static class MagnificationModeInfo extends ItemInfoArrayAdapter.ItemInfo {
@MagnificationMode
public final int mMagnificationMode;
MagnificationModeInfo(@NonNull CharSequence title, @Nullable CharSequence summary,
@DrawableRes int drawableId, @MagnificationMode int magnificationMode) {
super(title, summary, drawableId);
mMagnificationMode = magnificationMode;
}
}
private void initModePreference() {
mModePreference = findPreference(PREF_KEY_MODE);
mModePreference.setOnPreferenceClickListener(preference -> {
mCapabilities = MagnificationCapabilities.getCapabilities(getPrefContext());
showDialog(DIALOG_MAGNIFICATION_CAPABILITY);
return true;
});
}
private void onSwitchShortcutDialogPositiveButtonClicked(View view) {
//TODO(b/147990389): Merge this function into util until magnification change format to
// Component.
optOutMagnificationFromTripleTap();
optInMagnificationToAccessibilityButton();
mDialog.dismiss();
}
private void optOutMagnificationFromTripleTap() {
Settings.Secure.putInt(getPrefContext().getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF);
}
private void optInMagnificationToAccessibilityButton() {
final String targetKey = Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
final String targetString = Settings.Secure.getString(getPrefContext().getContentResolver(),
targetKey);
if (targetString.contains(MAGNIFICATION_CONTROLLER_NAME)) {
return;
}
final StringJoiner joiner = new StringJoiner(String.valueOf(COMPONENT_NAME_SEPARATOR));
if (!TextUtils.isEmpty(targetString)) {
joiner.add(targetString);
}
joiner.add(MAGNIFICATION_CONTROLLER_NAME);
Settings.Secure.putString(getPrefContext().getContentResolver(), targetKey,
joiner.toString());
}
private boolean isTripleTapEnabled() {
return Settings.Secure.getInt(getPrefContext().getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, OFF) == ON;
throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =

View File

@@ -56,4 +56,11 @@ public final class MagnificationCapabilitiesTest {
R.string.accessibility_magnification_area_settings_full_screen_summary);
assertThat(actualString).isEqualTo(expectedString);
}
@Test
public void getCapabilities_unset_defaultValue() {
final int windowCapabilities = MagnificationCapabilities.getCapabilities(mContext);
assertThat(windowCapabilities).isEqualTo(
MagnificationCapabilities.MagnificationMode.FULLSCREEN);
}
}

View File

@@ -16,40 +16,143 @@
package com.android.settings.accessibility;
import static androidx.lifecycle.Lifecycle.Event.ON_CREATE;
import static com.android.settings.accessibility.AccessibilityEditDialogUtils.CustomButton;
import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import static com.android.settings.accessibility.MagnificationModePreferenceController.MagnificationModeInfo;
import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowDashboardFragment;
import com.android.settingslib.core.AbstractPreferenceController;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowDashboardFragment.class)
public class MagnificationModePreferenceControllerTest {
private static final String PREF_KEY = "screen_magnification_mode";
private static final String KEY_CAPABILITY =
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_CAPABILITY;
private static final int WINDOW_SCREEN_VALUE = 2;
private static final int ALL_VALUE = 3;
private static final int MAGNIFICATION_MODE_DEFAULT = MagnificationMode.ALL;
@Rule
public MockitoRule mocks = MockitoJUnit.rule();
@Mock
private PreferenceScreen mScreen;
private Context mContext;
private TestMagnificationSettingsFragment mFragment;
private MagnificationModePreferenceController mController;
private Preference mModePreference;
@Before
public void setUp() {
mContext = RuntimeEnvironment.application;
mController = new MagnificationModePreferenceController(mContext, PREF_KEY);
mScreen = spy(new PreferenceScreen(mContext, null));
mModePreference = new Preference(mContext);
mFragment = spy(new TestMagnificationSettingsFragment(mController));
doReturn(mScreen).when(mFragment).getPreferenceScreen();
doReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS)).when(
mFragment).getChildFragmentManager();
mContext.setTheme(R.style.Theme_AppCompat);
doReturn(mModePreference).when(mScreen).findPreference(PREF_KEY);
MagnificationCapabilities.setCapabilities(mContext, MAGNIFICATION_MODE_DEFAULT);
showPreferenceOnTheScreen(null);
mModePreference.getOnPreferenceClickListener().onPreferenceClick(mModePreference);
}
@Test
public void settingsModeIsDefault_checkedModeInDialogIsDefault() {
assertThat(getCheckedModeFromDialog()).isEqualTo(
MAGNIFICATION_MODE_DEFAULT);
}
@Test
public void choseModeIsDifferentFromInSettings_checkedModeInDialogIsExpected() {
performItemClickWith(MagnificationMode.WINDOW);
assertThat(getCheckedModeFromDialog()).isEqualTo(MagnificationMode.WINDOW);
}
@Test
public void dialogIsReCreated_settingsModeIsAllAndChoseWindowMode_checkedModeIsWindow() {
showPreferenceOnTheScreen(null);
performItemClickWith(MagnificationMode.WINDOW);
reshowPreferenceOnTheScreen();
mFragment.showDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE);
assertThat(getCheckedModeFromDialog()).isEqualTo(
MagnificationMode.WINDOW);
}
@Test
public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() {
enableTripleTap();
performItemClickWith(MagnificationMode.WINDOW);
verify(mFragment).showDialog(
MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
@Test
public void chooseModeAll_modeAllInSettingsAndTripleTapEnabled_notShowShortcutDialog() {
enableTripleTap();
MagnificationCapabilities.setCapabilities(mContext,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationModePreferenceController.DIALOG_MAGNIFICATION_MODE);
performItemClickWith(MagnificationMode.ALL);
verify(mFragment, never()).showDialog(
MagnificationModePreferenceController.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
@Test
public void onSwitchShortcutDialogPositiveButtonClicked_TripleTapEnabled_TripleTapDisabled() {
enableTripleTap();
mController.onSwitchShortcutDialogButtonClicked(CustomButton.POSITIVE);
assertThat(MagnificationModePreferenceController.isTripleTapEnabled(mContext)).isFalse();
}
@Test
public void getSummary_saveWindowScreen_shouldReturnWindowScreenSummary() {
Settings.Secure.putInt(mContext.getContentResolver(),
KEY_CAPABILITY, WINDOW_SCREEN_VALUE);
MagnificationCapabilities.setCapabilities(mContext, MagnificationMode.WINDOW);
assertThat(mController.getSummary())
.isEqualTo(mContext.getString(
@@ -58,11 +161,93 @@ public class MagnificationModePreferenceControllerTest {
@Test
public void getSummary_saveAll_shouldReturnAllSummary() {
Settings.Secure.putInt(mContext.getContentResolver(),
KEY_CAPABILITY, ALL_VALUE);
MagnificationCapabilities.setCapabilities(mContext, MagnificationMode.ALL);
assertThat(mController.getSummary())
.isEqualTo(mContext.getString(
R.string.accessibility_magnification_area_settings_all_summary));
}
private int getCheckedModeFromDialog() {
final ListView listView = mController.mMagnificationModesListView;
assertThat(listView).isNotNull();
final int checkedPosition = listView.getCheckedItemPosition();
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) listView.getAdapter().getItem(checkedPosition);
return modeInfo.mMagnificationMode;
}
private void performItemClickWith(@MagnificationMode int mode) {
final ListView listView = mController.mMagnificationModesListView;
assertThat(listView).isNotNull();
int modeIndex = AdapterView.NO_ID;
// Index 0 is header.
for (int i = 1; i < listView.getAdapter().getCount(); i++) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) listView.getAdapter().getItem(i);
if (modeInfo.mMagnificationMode == mode) {
modeIndex = i;
break;
}
}
if (modeIndex == AdapterView.NO_ID) {
throw new RuntimeException("The mode is not in the list.");
}
listView.performItemClick(listView.getChildAt(modeIndex), modeIndex, modeIndex);
}
private void enableTripleTap() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON);
}
private void reshowPreferenceOnTheScreen() {
final Bundle bundle = new Bundle();
mFragment.onSaveInstanceState(bundle);
mFragment.onDetach();
showPreferenceOnTheScreen(bundle);
}
private void showPreferenceOnTheScreen(Bundle savedInstanceState) {
mFragment.onAttach(mContext);
mFragment.onCreate(savedInstanceState);
mController.displayPreference(mScreen);
}
private static class TestMagnificationSettingsFragment extends MagnificationSettingsFragment {
TestMagnificationSettingsFragment(AbstractPreferenceController... controllers) {
// Add given controllers for injection. Although controllers will be added in
// onAttach(). use(AbstractPreferenceController.class) returns the first added one.
for (int i = 0; i < controllers.length; i++) {
addPreferenceController(controllers[i]);
}
}
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
// Simulate the observable behaviour because ShadowDashFragment doesn't call
// super.create.
getSettingsLifecycle().onCreate(icicle);
getSettingsLifecycle().handleLifecycleEvent(ON_CREATE);
}
@Override
protected void showDialog(int dialogId) {
super.showDialog(dialogId);
// In current fragment architecture, we could assume onCreateDialog is called directly.
onCreateDialog(dialogId);
}
@Override
protected void addPreferenceController(AbstractPreferenceController controller) {
super.addPreferenceController(controller);
}
}
}

View File

@@ -16,201 +16,34 @@
package com.android.settings.accessibility;
import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import static com.android.settings.accessibility.MagnificationPreferenceFragment.ON;
import static com.android.settings.accessibility.MagnificationSettingsFragment.MagnificationModeInfo;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.AdapterView;
import android.widget.ListView;
import androidx.fragment.app.FragmentManager;
import androidx.preference.PreferenceManager;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
import com.android.settings.testutils.shadow.ShadowDashboardFragment;
import com.android.settings.testutils.XmlTestUtils;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import java.util.List;
/** Tests for {@link MagnificationSettingsFragment} */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = ShadowDashboardFragment.class)
public class MagnificationSettingsFragmentTest {
@Rule
public MockitoRule mocks = MockitoJUnit.rule();
@Mock
private PreferenceManager mPreferenceManager;
private static final String EXTRA_CAPABILITY =
MagnificationSettingsFragment.EXTRA_CAPABILITY;
private final Context mContext = ApplicationProvider.getApplicationContext();
private TestMagnificationSettingsFragment mFragment;
@Before
public void setUpFragment() {
mFragment = spy(new TestMagnificationSettingsFragment());
when(mFragment.getPreferenceManager()).thenReturn(mPreferenceManager);
when(mFragment.getPreferenceManager().getContext()).thenReturn(mContext);
doReturn(mock(FragmentManager.class, Answers.RETURNS_DEEP_STUBS)).when(
mFragment).getChildFragmentManager();
mContext.setTheme(R.style.Theme_AppCompat);
}
@Test
public void onCreateDialog_capabilitiesInBundle_checkedModeInDialogIsExpected() {
final Bundle windowModeSavedInstanceState = new Bundle();
windowModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mFragment.onCreate(windowModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.WINDOW);
}
@Test
public void onCreateDialog_capabilitiesInSetting_checkedModeInDialogIsExpected() {
MagnificationCapabilities.setCapabilities(mContext,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.FULLSCREEN);
}
@Test
public void onCreateDialog_choseModeIsDifferentFromInSettings_ShowUsersChoseModeInDialog() {
final Bundle allModeSavedInstanceState = new Bundle();
allModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_ALL);
MagnificationCapabilities.setCapabilities(mContext,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mFragment.onCreate(allModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.ALL);
}
@Test
public void onCreateDialog_emptySettingsAndBundle_checkedModeInDialogIsDefaultValue() {
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
assertThat(getChoseModeFromDialog()).isEqualTo(MagnificationMode.FULLSCREEN);
}
@Test
public void chooseWindowMode_tripleTapEnabled_showSwitchShortcutDialog() {
enableTripleTap();
final Bundle fullScreenModeSavedInstanceState = new Bundle();
fullScreenModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mFragment.onCreate(fullScreenModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
performItemClickWith(MagnificationMode.WINDOW);
verify(mFragment).showDialog(
MagnificationSettingsFragment.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
@Test
public void chooseModeAll_tripleTapEnabled_showSwitchShortcutDialog() {
enableTripleTap();
final Bundle fullScreenModeSavedInstanceState = new Bundle();
fullScreenModeSavedInstanceState.putInt(EXTRA_CAPABILITY,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
mFragment.onCreate(fullScreenModeSavedInstanceState);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
performItemClickWith(MagnificationMode.ALL);
verify(mFragment).showDialog(
MagnificationSettingsFragment.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
@Test
public void chooseWindowMode_WindowModeInSettingsAndTripleTapEnabled_notShowShortCutDialog() {
enableTripleTap();
MagnificationCapabilities.setCapabilities(mContext,
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
mFragment.onCreate(Bundle.EMPTY);
mFragment.onCreateDialog(MagnificationSettingsFragment.DIALOG_MAGNIFICATION_CAPABILITY);
performItemClickWith(MagnificationMode.WINDOW);
verify(mFragment, never()).showDialog(
MagnificationSettingsFragment.DIALOG_MAGNIFICATION_SWITCH_SHORTCUT);
}
private int getChoseModeFromDialog() {
final ListView listView = mFragment.mMagnificationModesListView;
assertThat(listView).isNotNull();
final int checkedPosition = listView.getCheckedItemPosition();
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) listView.getAdapter().getItem(
checkedPosition);
return modeInfo.mMagnificationMode;
}
private void performItemClickWith(@MagnificationMode int mode) {
final ListView listView = mFragment.mMagnificationModesListView;
assertThat(listView).isNotNull();
int modeIndex = AdapterView.NO_ID;
// Index 0 is header.
for (int i = 1; i < listView.getAdapter().getCount(); i++) {
final MagnificationModeInfo modeInfo =
(MagnificationModeInfo) listView.getAdapter().getItem(i);
if (modeInfo.mMagnificationMode == mode) {
modeIndex = i;
break;
}
}
if (modeIndex == AdapterView.NO_ID) {
throw new RuntimeException("The mode is not in the list.");
}
listView.performItemClick(listView.getChildAt(modeIndex), modeIndex, modeIndex);
}
private void enableTripleTap() {
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED, ON);
}
public static class TestMagnificationSettingsFragment extends MagnificationSettingsFragment {
public TestMagnificationSettingsFragment() {}
@Override
protected void showDialog(int dialogId) {
super.showDialog(dialogId);
}
public void getNonIndexableKeys_existInXmlLayout() {
final List<String> niks =
ShortcutsSettingsFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List<String> keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext,
R.xml.accessibility_magnification_service_settings);
assertThat(keys).containsAtLeastElementsIn(niks);
}
}