Extract the logic of MagnificationMode to the controller

To move the preference to the upper layer, we extract all logics
to its controller.

We move all tests to the test files and add server tests to
verify the behaviour of edit shortcut dialog.

Bug: 182992338
Test: atest  MagnificationModePreferenceControllerTest

Change-Id: I34c4361e2e116a22c3e34bd35c8ac8cac752ab96
This commit is contained in:
ryanlwlin
2021-04-01 17:25:48 +08:00
parent 9d14071637
commit 8e5e4dec12
8 changed files with 531 additions and 429 deletions

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;
}
}
}