Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8e5e4dec authored by ryanlwlin's avatar ryanlwlin
Browse files

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
parent 9d140716
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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"/>
+49 −14
Original line number Diff line number Diff line
@@ -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);

    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.switch_shortcut_positive_button);
                R.id.custom_positive_button);
        final Button negativeButton = contentView.findViewById(
                R.id.switch_shortcut_negative_button);
                R.id.custom_negative_button);

        if (positiveButton != null) {
            positiveButton.setOnClickListener(v -> {
                if (positiveBtnListener != null) {
                    positiveBtnListener.onClick(CustomButton.POSITIVE);
                }
                dialog.dismiss();
            });
        }

        positiveButton.setOnClickListener(listener);
        negativeButton.setOnClickListener(v -> dialog.dismiss());
        if (negativeButton != null) {
            negativeButton.setOnClickListener(v -> {
                if (negativeBtnListener != null) {
                    negativeBtnListener.onClick(CustomButton.NEGATIVE);
                }
                dialog.dismiss();
            });
        }
    }

    private static View createSwitchShortcutDialogContentView(Context context) {
+2 −0
Original line number Diff line number Diff line
@@ -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;
+243 −3
Original line number Diff line number Diff line
@@ -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;

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

/** Controller that shows the magnification area mode summary. */
public class MagnificationModePreferenceController extends BasePreferenceController {
    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;
        }
    }
}
+18 −218

File changed.

Preview size limit exceeded, changes collapsed.

Loading