Merge "[Settings] Refactor AirplaneModeEnabler with test"
diff --git a/res/layout/accessibility_shortcut_secondary_action.xml b/res/layout/accessibility_shortcut_secondary_action.xml
index b46c303..caf9b1c 100644
--- a/res/layout/accessibility_shortcut_secondary_action.xml
+++ b/res/layout/accessibility_shortcut_secondary_action.xml
@@ -87,6 +87,7 @@
     </LinearLayout>
 
     <View
+        android:id="@+id/divider"
         android:layout_width="1dp"
         android:layout_height="match_parent"
         android:layout_marginTop="16dp"
diff --git a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
index 1d87477..7136172 100644
--- a/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilityEditDialogUtils.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.TypedArray;
@@ -245,27 +243,21 @@
         });
     }
 
-    private static boolean isGestureNavigateEnabled(Context context) {
-        return context.getResources().getInteger(
-                com.android.internal.R.integer.config_navBarInteractionMode)
-                == NAV_BAR_MODE_GESTURAL;
-    }
-
     private static CharSequence retrieveTitle(Context context) {
-        return context.getString(isGestureNavigateEnabled(context)
+        return context.getString(AccessibilityUtil.isGestureNavigateEnabled(context)
                 ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
                 : R.string.accessibility_shortcut_edit_dialog_title_software);
     }
 
     private static CharSequence retrieveSummary(Context context, int lineHeight) {
-        return isGestureNavigateEnabled(context)
+        return AccessibilityUtil.isGestureNavigateEnabled(context)
                 ? context.getString(
                 R.string.accessibility_shortcut_edit_dialog_summary_software_gesture)
                 : getSummaryStringWithIcon(context, lineHeight);
     }
 
     private static int retrieveImageResId(Context context) {
-        return isGestureNavigateEnabled(context)
+        return AccessibilityUtil.isGestureNavigateEnabled(context)
                 ? R.drawable.accessibility_shortcut_type_software_gesture
                 : R.drawable.accessibility_shortcut_type_software;
         // TODO(b/142531156): Use vector drawable instead of temporal png file to avoid distorted.
diff --git a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
index 153fa19..5e6eced 100644
--- a/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
+++ b/src/com/android/settings/accessibility/AccessibilityGestureNavigationTutorial.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.TypedArray;
@@ -83,7 +81,7 @@
         final AlertDialog alertDialog = createDialog(context,
                 DialogType.LAUNCH_SERVICE_BY_ACCESSIBILITY_BUTTON);
 
-        if (!isGestureNavigateEnabled(context)) {
+        if (!AccessibilityUtil.isGestureNavigateEnabled(context)) {
             updateMessageWithIcon(context, alertDialog);
         }
 
@@ -206,12 +204,6 @@
         return colorResId;
     }
 
-    private static boolean isGestureNavigateEnabled(Context context) {
-        return context.getResources().getInteger(
-                com.android.internal.R.integer.config_navBarInteractionMode)
-                == NAV_BAR_MODE_GESTURAL;
-    }
-
     private static boolean isTouchExploreOn(Context context) {
         return ((AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE))
                 .isTouchExplorationEnabled();
diff --git a/src/com/android/settings/accessibility/AccessibilityUtil.java b/src/com/android/settings/accessibility/AccessibilityUtil.java
index a3682b2..4b3a341 100644
--- a/src/com/android/settings/accessibility/AccessibilityUtil.java
+++ b/src/com/android/settings/accessibility/AccessibilityUtil.java
@@ -16,6 +16,8 @@
 
 package com.android.settings.accessibility;
 
+import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.content.Context;
 import android.os.Build;
@@ -55,18 +57,78 @@
     }
 
     /**
+     * Annotation for different shortcut type UI type.
+     *
+     * {@code DEFAULT} for displaying default value.
+     * {@code SOFTWARE} for displaying specifying the accessibility services or features which
+     * choose accessibility button in the navigation bar as preferred shortcut.
+     * {@code HARDWARE} for displaying specifying the accessibility services or features which
+     * choose accessibility shortcut as preferred shortcut.
+     * {@code TRIPLETAP} for displaying specifying magnification to be toggled via quickly
+     * tapping screen 3 times as preferred shortcut.
+     */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef({
+            ShortcutType.DEFAULT,
+            ShortcutType.SOFTWARE,
+            ShortcutType.HARDWARE,
+            ShortcutType.TRIPLETAP,
+    })
+
+    /** Denotes the shortcut type. */
+    public @interface ShortcutType {
+        int DEFAULT = 0;
+        int SOFTWARE = 1; // 1 << 0
+        int HARDWARE = 2; // 1 << 1
+        int TRIPLETAP = 4; // 1 << 2
+    }
+
+    /** Denotes the accessibility enabled status */
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface State {
+        int OFF = 0;
+        int ON = 1;
+    }
+
+    /**
      * Return On/Off string according to the setting which specifies the integer value 1 or 0. This
      * setting is defined in the secure system settings {@link android.provider.Settings.Secure}.
      */
     static CharSequence getSummary(Context context, String settingsSecureKey) {
         final boolean enabled = Settings.Secure.getInt(context.getContentResolver(),
-                settingsSecureKey, 0) == 1;
+                settingsSecureKey, State.OFF) == State.ON;
         final int resId = enabled ? R.string.accessibility_feature_state_on
                 : R.string.accessibility_feature_state_off;
         return context.getResources().getText(resId);
     }
 
     /**
+     * Capitalizes a string by capitalizing the first character and making the remaining characters
+     * lower case.
+     */
+    public static String capitalize(String stringToCapitalize) {
+        if (stringToCapitalize == null) {
+            return null;
+        }
+
+        StringBuilder capitalizedString = new StringBuilder();
+        if (stringToCapitalize.length() > 0) {
+            capitalizedString.append(stringToCapitalize.substring(0, 1).toUpperCase());
+            if (stringToCapitalize.length() > 1) {
+                capitalizedString.append(stringToCapitalize.substring(1).toLowerCase());
+            }
+        }
+        return capitalizedString.toString();
+    }
+
+    /** Determines if a gesture navigation bar is being used. */
+    public static boolean isGestureNavigateEnabled(Context context) {
+        return context.getResources().getInteger(
+                com.android.internal.R.integer.config_navBarInteractionMode)
+                == NAV_BAR_MODE_GESTURAL;
+    }
+
+    /**
      * Gets the corresponding fragment type of a given accessibility service
      *
      * @param accessibilityServiceInfo The accessibilityService's info
diff --git a/src/com/android/settings/accessibility/LegacyAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/LegacyAccessibilityServicePreferenceFragment.java
index a55f53a..4714fb3 100644
--- a/src/com/android/settings/accessibility/LegacyAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/LegacyAccessibilityServicePreferenceFragment.java
@@ -21,6 +21,8 @@
 
 import androidx.preference.PreferenceScreen;
 
+import com.android.settings.R;
+
 /** For accessibility services that target SDK <= Q. */
 public class LegacyAccessibilityServicePreferenceFragment extends
         ToggleAccessibilityServicePreferenceFragment {
@@ -29,10 +31,13 @@
         super.onViewCreated(view, savedInstanceState);
 
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        final ShortcutPreference preference = preferenceScreen.findPreference(
+        final ShortcutPreference shortcutPreference = preferenceScreen.findPreference(
                 getShortcutPreferenceKey());
-        if (preference != null) {
-            preference.setSettingsVisibility(View.GONE);
+        if (shortcutPreference != null) {
+            final CharSequence hardwareTitle = getPrefContext().getText(
+                    R.string.accessibility_shortcut_edit_dialog_title_hardware);
+            shortcutPreference.setSummary(hardwareTitle);
+            shortcutPreference.setSettingsVisibility(View.GONE);
         }
     }
 }
diff --git a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
index 834e0c6..2b618cb 100644
--- a/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/MagnificationPreferenceFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.settings.SettingsEnums;
 import android.content.ComponentName;
@@ -25,7 +23,6 @@
 import android.content.Context;
 import android.content.res.Resources;
 import android.os.Bundle;
-import android.provider.SearchIndexableResource;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.view.accessibility.AccessibilityManager;
@@ -36,12 +33,10 @@
 import com.android.settings.R;
 import com.android.settings.dashboard.DashboardFragment;
 import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.Indexable;
 import com.android.settings.search.actionbar.SearchMenuController;
 import com.android.settings.support.actionbar.HelpResourceProvider;
 import com.android.settingslib.search.SearchIndexable;
 
-import java.util.Arrays;
 import java.util.List;
 
 @SearchIndexable
@@ -134,7 +129,7 @@
                 if (info.getComponentName().equals(assignedComponentName)) {
                     final CharSequence assignedServiceName = info.getResolveInfo().loadLabel(
                             context.getPackageManager());
-                    final int messageId = isGestureNavigateEnabled(context)
+                    final int messageId = AccessibilityUtil.isGestureNavigateEnabled(context)
                             ? R.string.accessibility_screen_magnification_gesture_navigation_warning
                             : R.string.accessibility_screen_magnification_navbar_configuration_warning;
                     return context.getString(messageId, assignedServiceName);
@@ -161,12 +156,6 @@
         return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
     }
 
-    private static boolean isGestureNavigateEnabled(Context context) {
-        return context.getResources().getInteger(
-                com.android.internal.R.integer.config_navBarInteractionMode)
-                == NAV_BAR_MODE_GESTURAL;
-    }
-
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider(R.xml.accessibility_magnification_settings) {
 
diff --git a/src/com/android/settings/accessibility/ShortcutPreference.java b/src/com/android/settings/accessibility/ShortcutPreference.java
index f76bb01..b66a2b6 100644
--- a/src/com/android/settings/accessibility/ShortcutPreference.java
+++ b/src/com/android/settings/accessibility/ShortcutPreference.java
@@ -73,9 +73,11 @@
         }
 
         final View settings = holder.itemView.findViewById(android.R.id.widget_frame);
-        if (settings != null) {
+        final View divider = holder.itemView.findViewById(R.id.divider);
+        if (settings != null && divider != null) {
             settings.setOnClickListener(view -> callOnSettingsClicked());
             settings.setVisibility(mSettingsVisibility);
+            divider.setVisibility(mSettingsVisibility);
         }
     }
 
diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
index 3248e00..269bc04 100644
--- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java
@@ -16,8 +16,6 @@
 
 package com.android.settings.accessibility;
 
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-
 import android.accessibilityservice.AccessibilityServiceInfo;
 import android.app.Activity;
 import android.app.Dialog;
@@ -43,17 +41,22 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityManager;
+import android.widget.CheckBox;
 
 import androidx.preference.PreferenceScreen;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.ShortcutType;
 import com.android.settings.password.ConfirmDeviceCredentialActivity;
 import com.android.settings.widget.SwitchBar;
 import com.android.settings.widget.ToggleSwitch;
 import com.android.settings.widget.ToggleSwitch.OnBeforeCheckedChangeListener;
 import com.android.settingslib.accessibility.AccessibilityUtils;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.List;
 
 /** Fragment for providing toggle bar and basic accessibility service setup. */
@@ -61,22 +64,18 @@
         ToggleFeaturePreferenceFragment implements ShortcutPreference.OnClickListener {
 
     private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
-    private static final int DIALOG_ID_ENABLE_WARNING = 1;
-    private static final int DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL = 2;
-    private static final int DIALOG_ID_EDIT_SHORTCUT = 3;
+    private static final String EXTRA_SHORTCUT_TYPE = "shortcutType";
+    // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+    private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
+    private ShortcutPreference mShortcutPreference;
+    private int mShortcutType = ShortcutType.DEFAULT;
+    private CheckBox mSoftwareTypeCheckBox;
+    private CheckBox mHardwareTypeCheckBox;
 
     public static final int ACTIVITY_REQUEST_CONFIRM_CREDENTIAL_FOR_WEAKER_ENCRYPTION = 1;
-
     private CharSequence mDialogTitle;
-
     private LockPatternUtils mLockPatternUtils;
 
-    private final DialogInterface.OnClickListener mDialogListener =
-            (DialogInterface dialog, int id) -> {
-                if (id == DialogInterface.BUTTON_POSITIVE) {
-                    // TODO(b/142531156): Save the shortcut type preference.
-                }
-            };
 
     private final SettingsContentObserver mSettingsContentObserver =
             new SettingsContentObserver(new Handler()) {
@@ -99,7 +98,7 @@
                     } else {
                         handleConfirmServiceEnabled(true);
                         if (isServiceSupportAccessibilityButton()) {
-                            showDialog(DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL);
+                            showDialog(DialogType.LAUNCH_ACCESSIBILITY_TUTORIAL);
                         }
                     }
                 } else if (view.getId() == R.id.permission_enable_deny_button) {
@@ -131,11 +130,17 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        initShortcutPreference();
+        initShortcutPreference(savedInstanceState);
         return super.onCreateView(inflater, container, savedInstanceState);
     }
 
     @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
     public void onResume() {
         mSettingsContentObserver.register(getContentResolver());
         updateSwitchBarToggleSwitch();
@@ -176,7 +181,7 @@
     @Override
     public Dialog onCreateDialog(int dialogId) {
         switch (dialogId) {
-            case DIALOG_ID_ENABLE_WARNING: {
+            case DialogType.ENABLE_WARNING: {
                 final AccessibilityServiceInfo info = getAccessibilityServiceInfo();
                 if (info == null) {
                     return null;
@@ -185,8 +190,8 @@
                         .createCapabilitiesDialog(getActivity(), info, mViewOnClickListener);
                 break;
             }
-            case DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL: {
-                if (isGestureNavigateEnabled()) {
+            case DialogType.LAUNCH_ACCESSIBILITY_TUTORIAL: {
+                if (AccessibilityUtil.isGestureNavigateEnabled(getContext())) {
                     mDialog = AccessibilityGestureNavigationTutorial
                             .showGestureNavigationTutorialDialog(getActivity());
                 } else {
@@ -195,30 +200,129 @@
                 }
                 break;
             }
-            case DIALOG_ID_EDIT_SHORTCUT: {
+            case DialogType.EDIT_SHORTCUT: {
                 final CharSequence dialogTitle = getActivity().getString(
                         R.string.accessibility_shortcut_edit_dialog_title, mDialogTitle);
                 mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
-                        dialogTitle, mDialogListener);
+                        dialogTitle, this::callOnAlertDialogCheckboxClicked);
+                initializeDialogCheckBox(mDialog);
                 break;
             }
             default: {
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
             }
         }
         return mDialog;
     }
 
+    private void initializeDialogCheckBox(Dialog dialog) {
+        final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut);
+        mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox);
+        final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut);
+        mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox);
+        updateAlertDialogCheckState();
+        updateAlertDialogEnableState();
+    }
+
+    private void updateAlertDialogCheckState() {
+        updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE);
+        updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE);
+    }
+
+    private void updateAlertDialogEnableState() {
+        if (!mSoftwareTypeCheckBox.isChecked()) {
+            mHardwareTypeCheckBox.setEnabled(false);
+        } else if (!mHardwareTypeCheckBox.isChecked()) {
+            mSoftwareTypeCheckBox.setEnabled(false);
+        } else {
+            mSoftwareTypeCheckBox.setEnabled(true);
+            mHardwareTypeCheckBox.setEnabled(true);
+        }
+    }
+
+    private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) {
+        checkBox.setChecked((mShortcutType & type) == type);
+        checkBox.setOnClickListener(v -> {
+            updateShortcutType(false);
+            updateAlertDialogEnableState();
+        });
+    }
+
+    private void updateShortcutType(boolean saveToDB) {
+        mShortcutType = ShortcutType.DEFAULT;
+        if (mSoftwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.SOFTWARE;
+        }
+        if (mHardwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.HARDWARE;
+        }
+        if (saveToDB) {
+            setShortcutType(mShortcutType);
+        }
+    }
+
+    private void setSecureIntValue(String key, @ShortcutType int value) {
+        Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
+                key, value, getPrefContext().getContentResolver().getUserId());
+    }
+
+    private void setShortcutType(@ShortcutType int type) {
+        setSecureIntValue(KEY_SHORTCUT_TYPE, type);
+    }
+
+    private String getShortcutTypeSummary(Context context) {
+        final int shortcutType = getShortcutType(context);
+        final CharSequence softwareTitle =
+                context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
+                ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
+                : R.string.accessibility_shortcut_edit_dialog_title_software);
+
+        List<CharSequence> list = new ArrayList<>();
+        if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) {
+            list.add(softwareTitle);
+        }
+        if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) {
+            final CharSequence hardwareTitle = context.getText(
+                    R.string.accessibility_shortcut_edit_dialog_title_hardware);
+            list.add(hardwareTitle);
+        }
+
+        // Show software shortcut if first time to use.
+        if (list.isEmpty()) {
+            list.add(softwareTitle);
+        }
+        final String joinStrings = TextUtils.join(/* delimiter= */", ", list);
+        return AccessibilityUtil.capitalize(joinStrings);
+    }
+
+    @ShortcutType
+    private int getShortcutType(Context context) {
+        return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE);
+    }
+
+    @ShortcutType
+    private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) {
+        return Settings.Secure.getIntForUser(
+                context.getContentResolver(),
+                key, defaultValue, context.getContentResolver().getUserId());
+    }
+
+    private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+        updateShortcutType(true);
+        mShortcutPreference.setSummary(
+                getShortcutTypeSummary(getPrefContext()));
+    }
+
     @Override
     public int getDialogMetricsCategory(int dialogId) {
         switch (dialogId) {
-            case DIALOG_ID_ENABLE_WARNING:
+            case DialogType.ENABLE_WARNING:
                 return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_ENABLE;
-            case DIALOG_ID_LAUNCH_ACCESSIBILITY_TUTORIAL:
-                return isGestureNavigateEnabled()
+            case DialogType.LAUNCH_ACCESSIBILITY_TUTORIAL:
+                return AccessibilityUtil.isGestureNavigateEnabled(getContext())
                         ? SettingsEnums.DIALOG_TOGGLE_SCREEN_GESTURE_NAVIGATION
                         : SettingsEnums.DIALOG_TOGGLE_SCREEN_ACCESSIBILITY_BUTTON;
-            case DIALOG_ID_EDIT_SHORTCUT:
+            case DialogType.EDIT_SHORTCUT:
                 return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
             default:
                 return 0;
@@ -234,21 +338,29 @@
         switchBar.setSwitchBarText(switchBarText, switchBarText);
     }
 
-    private void initShortcutPreference() {
-        final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        final ShortcutPreference shortcutPreference = new ShortcutPreference(
-                preferenceScreen.getContext(), null);
-        // Put the shortcutPreference before settingsPreference.
-        shortcutPreference.setPersistent(false);
-        shortcutPreference.setKey(getShortcutPreferenceKey());
-        shortcutPreference.setOrder(-1);
-        shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
-        shortcutPreference.setOnClickListener(this);
+    private void initShortcutPreference(Bundle savedInstanceState) {
+        // Restore the Shortcut type
+        if (savedInstanceState != null) {
+            mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT);
+        }
+        if (mShortcutType == ShortcutType.DEFAULT) {
+            mShortcutType = getShortcutType(getPrefContext());
+        }
 
-        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
-        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        // Initial ShortcutPreference widget
+        final PreferenceScreen preferenceScreen = getPreferenceScreen();
+        mShortcutPreference = new ShortcutPreference(
+                preferenceScreen.getContext(), null);
+        mShortcutPreference.setPersistent(false);
+        mShortcutPreference.setKey(getShortcutPreferenceKey());
+        mShortcutPreference.setOrder(-1);
+        mShortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+        mShortcutPreference.setOnClickListener(this);
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
+        // Put the shortcutPreference before settingsPreference.
+        mShortcutPreference.setOrder(-1);
+        preferenceScreen.addPreference(mShortcutPreference);
         // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
-        preferenceScreen.addPreference(shortcutPreference);
     }
 
     public String getShortcutPreferenceKey() {
@@ -290,12 +402,6 @@
         }
     }
 
-    private boolean isGestureNavigateEnabled() {
-        return getContext().getResources().getInteger(
-                com.android.internal.R.integer.config_navBarInteractionMode)
-                == NAV_BAR_MODE_GESTURAL;
-    }
-
     private boolean isServiceSupportAccessibilityButton() {
         final AccessibilityManager ams = (AccessibilityManager) getContext().getSystemService(
                 Context.ACCESSIBILITY_SERVICE);
@@ -346,7 +452,7 @@
                 if (checked) {
                     mSwitchBar.setCheckedInternal(false);
                     getArguments().putBoolean(AccessibilitySettings.EXTRA_CHECKED, false);
-                    showDialog(DIALOG_ID_ENABLE_WARNING);
+                    showDialog(DialogType.ENABLE_WARNING);
                 } else {
                     handleConfirmServiceEnabled(false);
                 }
@@ -366,7 +472,8 @@
 
     @Override
     public void onSettingsClicked(ShortcutPreference preference) {
-        showDialog(DIALOG_ID_EDIT_SHORTCUT);
+        mShortcutType = getShortcutType(getPrefContext());
+        showDialog(DialogType.EDIT_SHORTCUT);
     }
 
     @Override
@@ -402,4 +509,11 @@
         mDialogTitle = getAccessibilityServiceInfo().getResolveInfo().loadLabel(
                 getPackageManager());
     }
+
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface DialogType {
+        int ENABLE_WARNING = 1;
+        int LAUNCH_ACCESSIBILITY_TUTORIAL = 2;
+        int EDIT_SHORTCUT = 3;
+    }
 }
diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
index 880efb6..1c7a5f3 100644
--- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
@@ -18,26 +18,30 @@
 
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
+import android.content.Context;
 import android.content.DialogInterface;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.CheckBox;
 import android.widget.Switch;
 
+import androidx.appcompat.app.AlertDialog;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.ShortcutType;
+import com.android.settings.accessibility.AccessibilityUtil.State;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.search.SearchIndexable;
 
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -52,15 +56,15 @@
     private static final int DIALOG_ID_EDIT_SHORTCUT = 1;
     private static final String DISPLAY_INVERSION_ENABLED =
             Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED;
-    private final DialogInterface.OnClickListener mDialogListener =
-            (DialogInterface dialog, int id) -> {
-                if (id == DialogInterface.BUTTON_POSITIVE) {
-                    // TODO(b/142531156): Save the shortcut type preference.
-                }
-            };
+    private static final String EXTRA_SHORTCUT_TYPE = "shortcutType";
+    // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+    private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
     private final Handler mHandler = new Handler();
-    private Dialog mDialog;
+    private ShortcutPreference mShortcutPreference;
     private SettingsContentObserver mSettingsContentObserver;
+    private int mShortcutType = ShortcutType.DEFAULT;
+    private CheckBox mSoftwareTypeCheckBox;
+    private CheckBox mHardwareTypeCheckBox;
 
     @Override
     public void onStart() {
@@ -119,10 +123,10 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        initShortcutPreference();
-        final List<String> shortcutFeatureKeys = new ArrayList<>(1);
-        shortcutFeatureKeys.add(DISPLAY_INVERSION_ENABLED);
-        mSettingsContentObserver = new SettingsContentObserver(mHandler, shortcutFeatureKeys) {
+        initShortcutPreference(savedInstanceState);
+        final List<String> enableServiceFeatureKeys = new ArrayList<>(/* initialCapacity= */ 1);
+        enableServiceFeatureKeys.add(DISPLAY_INVERSION_ENABLED);
+        mSettingsContentObserver = new SettingsContentObserver(mHandler, enableServiceFeatureKeys) {
             @Override
             public void onChange(boolean selfChange, Uri uri) {
                 mSwitchBar.setCheckedInternal(
@@ -134,15 +138,121 @@
     }
 
     @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
     public Dialog onCreateDialog(int dialogId) {
         if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
             final CharSequence dialogTitle = getActivity().getString(
                     R.string.accessibility_shortcut_edit_dialog_title_daltonizer);
-            mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
-                    dialogTitle, mDialogListener);
+            final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+                    getActivity(),
+                    dialogTitle, this::callOnAlertDialogCheckboxClicked);
+            initializeDialogCheckBox(dialog);
+            return dialog;
+        }
+        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+    }
+
+    private void initializeDialogCheckBox(AlertDialog dialog) {
+        final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut);
+        mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox);
+        final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut);
+        mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox);
+        updateAlertDialogCheckState();
+        updateAlertDialogEnableState();
+    }
+
+    private void updateAlertDialogCheckState() {
+        updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE);
+        updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE);
+    }
+
+    private void updateAlertDialogEnableState() {
+        if (!mSoftwareTypeCheckBox.isChecked()) {
+            mHardwareTypeCheckBox.setEnabled(false);
+        } else if (!mHardwareTypeCheckBox.isChecked()) {
+            mSoftwareTypeCheckBox.setEnabled(false);
+        } else {
+            mSoftwareTypeCheckBox.setEnabled(true);
+            mHardwareTypeCheckBox.setEnabled(true);
+        }
+    }
+
+    private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) {
+        checkBox.setChecked((mShortcutType & type) == type);
+        checkBox.setOnClickListener(v -> {
+            updateShortcutType(false);
+            updateAlertDialogEnableState();
+        });
+    }
+
+    private void updateShortcutType(boolean saveToDB) {
+        mShortcutType = ShortcutType.DEFAULT;
+        if (mSoftwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.SOFTWARE;
+        }
+        if (mHardwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.HARDWARE;
+        }
+        if (saveToDB) {
+            setShortcutType(mShortcutType);
+        }
+    }
+
+    private void setSecureIntValue(String key, @ShortcutType int value) {
+        Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
+                key, value, getPrefContext().getContentResolver().getUserId());
+    }
+
+    private void setShortcutType(@ShortcutType int type) {
+        setSecureIntValue(KEY_SHORTCUT_TYPE, type);
+    }
+
+    private String getShortcutTypeSummary(Context context) {
+        final int shortcutType = getShortcutType(context);
+        final CharSequence softwareTitle =
+                context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
+                        ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
+                        : R.string.accessibility_shortcut_edit_dialog_title_software);
+
+        List<CharSequence> list = new ArrayList<>();
+        if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) {
+            list.add(softwareTitle);
+        }
+        if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) {
+            final CharSequence hardwareTitle = context.getText(
+                    R.string.accessibility_shortcut_edit_dialog_title_hardware);
+            list.add(hardwareTitle);
         }
 
-        return mDialog;
+        // Show software shortcut if first time to use.
+        if (list.isEmpty()) {
+            list.add(softwareTitle);
+        }
+        final String joinStrings = TextUtils.join(/* delimiter= */", ", list);
+        return AccessibilityUtil.capitalize(joinStrings);
+    }
+
+    @ShortcutType
+    private int getShortcutType(Context context) {
+        return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE);
+    }
+
+    @ShortcutType
+    private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) {
+        return Settings.Secure.getIntForUser(
+                context.getContentResolver(),
+                key, defaultValue, context.getContentResolver().getUserId());
+    }
+
+    private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+        updateShortcutType(true);
+        mShortcutPreference.setSummary(
+                getShortcutTypeSummary(getPrefContext()));
     }
 
     @Override
@@ -153,21 +263,29 @@
         return 0;
     }
 
-    private void initShortcutPreference() {
+    private void initShortcutPreference(Bundle savedInstanceState) {
+        // Restore the Shortcut type
+        if (savedInstanceState != null) {
+            mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT);
+        }
+        if (mShortcutType == ShortcutType.DEFAULT) {
+            mShortcutType = getShortcutType(getPrefContext());
+        }
+
+        // Initial ShortcutPreference widget
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        final ShortcutPreference shortcutPreference = new ShortcutPreference(
+        mShortcutPreference = new ShortcutPreference(
                 preferenceScreen.getContext(), null);
         final Preference previewPreference = findPreference(PREVIEW_PREFERENCE_KEY);
         // Put the shortcutPreference before radioButtonPreference.
-        shortcutPreference.setPersistent(false);
-        shortcutPreference.setKey(getShortcutPreferenceKey());
-        shortcutPreference.setOrder(previewPreference.getOrder() - 1);
-        shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
-        shortcutPreference.setOnClickListener(this);
-        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
-        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        mShortcutPreference.setPersistent(false);
+        mShortcutPreference.setKey(getShortcutPreferenceKey());
+        mShortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+        mShortcutPreference.setOnClickListener(this);
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
+        mShortcutPreference.setOrder(previewPreference.getOrder() - 1);
+        preferenceScreen.addPreference(mShortcutPreference);
         // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
-        preferenceScreen.addPreference(shortcutPreference);
     }
 
     public String getShortcutPreferenceKey() {
@@ -185,15 +303,10 @@
 
     @Override
     public void onSettingsClicked(ShortcutPreference preference) {
+        mShortcutType = getShortcutType(getPrefContext());
         showDialog(DIALOG_ID_EDIT_SHORTCUT);
     }
 
-    @Retention(RetentionPolicy.SOURCE)
-    private @interface State {
-        int OFF = 0;
-        int ON = 1;
-    }
-
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
             new BaseSearchIndexProvider(R.xml.accessibility_color_inversion_settings);
 }
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
index a4f3e62..7fb05da 100644
--- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -23,15 +23,20 @@
 import android.content.res.Resources;
 import android.os.Bundle;
 import android.provider.Settings;
+import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.CheckBox;
 import android.widget.Switch;
 
+import androidx.appcompat.app.AlertDialog;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 
 import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.ShortcutType;
+import com.android.settings.accessibility.AccessibilityUtil.State;
 import com.android.settings.search.BaseSearchIndexProvider;
 import com.android.settings.widget.SwitchBar;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -48,9 +53,16 @@
         SwitchBar.OnSwitchChangeListener, ShortcutPreference.OnClickListener {
 
     private static final String ENABLED = Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED;
-    private static final String RADIOPREFERENCE_KEY = "daltonizer_mode_deuteranomaly";
+    private static final String PREFERENCE_KEY = "daltonizer_mode_deuteranomaly";
+    private static final String EXTRA_SHORTCUT_TYPE = "shortcutType";
+    // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+    private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
     private static final int DIALOG_ID_EDIT_SHORTCUT = 1;
     private static final List<AbstractPreferenceController> sControllers = new ArrayList<>();
+    private ShortcutPreference mShortcutPreference;
+    private int mShortcutType = ShortcutType.DEFAULT;
+    private CheckBox mSoftwareTypeCheckBox;
+    private CheckBox mHardwareTypeCheckBox;
 
     private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
             Lifecycle lifecycle) {
@@ -67,15 +79,6 @@
         return sControllers;
     }
 
-    private final DialogInterface.OnClickListener mDialogListener =
-            (DialogInterface dialog, int id) -> {
-                if (id == DialogInterface.BUTTON_POSITIVE) {
-                    // TODO(b/142531156): Save the shortcut type preference.
-                }
-            };
-
-    private Dialog mDialog;
-
     @Override
     public void onCheckedChanged(Preference preference) {
         for (AbstractPreferenceController controller : sControllers) {
@@ -86,11 +89,17 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        initShortcutPreference();
+        initShortcutPreference(savedInstanceState);
         return super.onCreateView(inflater, container, savedInstanceState);
     }
 
     @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
         for (AbstractPreferenceController controller :
@@ -115,11 +124,111 @@
         if (dialogId == DIALOG_ID_EDIT_SHORTCUT) {
             final CharSequence dialogTitle = getActivity().getString(
                     R.string.accessibility_shortcut_edit_dialog_title_daltonizer);
-            mDialog = AccessibilityEditDialogUtils.showEditShortcutDialog(getActivity(),
-                    dialogTitle, mDialogListener);
+            final AlertDialog dialog = AccessibilityEditDialogUtils.showEditShortcutDialog(
+                    getActivity(),
+                    dialogTitle, this::callOnAlertDialogCheckboxClicked);
+            initializeDialogCheckBox(dialog);
+            return dialog;
+        }
+        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+    }
+
+    private void initializeDialogCheckBox(AlertDialog dialog) {
+        final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut);
+        mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox);
+        final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut);
+        mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox);
+        updateAlertDialogCheckState();
+        updateAlertDialogEnableState();
+    }
+
+    private void updateAlertDialogCheckState() {
+        updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE);
+        updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE);
+    }
+
+    private void updateAlertDialogEnableState() {
+        if (!mSoftwareTypeCheckBox.isChecked()) {
+            mHardwareTypeCheckBox.setEnabled(false);
+        } else if (!mHardwareTypeCheckBox.isChecked()) {
+            mSoftwareTypeCheckBox.setEnabled(false);
+        } else {
+            mSoftwareTypeCheckBox.setEnabled(true);
+            mHardwareTypeCheckBox.setEnabled(true);
+        }
+    }
+
+    private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) {
+        checkBox.setChecked((mShortcutType & type) == type);
+        checkBox.setOnClickListener(v -> {
+            updateShortcutType(false);
+            updateAlertDialogEnableState();
+        });
+    }
+
+    private void updateShortcutType(boolean saveToDB) {
+        mShortcutType = ShortcutType.DEFAULT;
+        if (mSoftwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.SOFTWARE;
+        }
+        if (mHardwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.HARDWARE;
+        }
+        if (saveToDB) {
+            setShortcutType(mShortcutType);
+        }
+    }
+
+    private void setSecureIntValue(String key, @ShortcutType int value) {
+        Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
+                key, value, getPrefContext().getContentResolver().getUserId());
+    }
+
+    private void setShortcutType(@ShortcutType int type) {
+        setSecureIntValue(KEY_SHORTCUT_TYPE, type);
+    }
+
+    private String getShortcutTypeSummary(Context context) {
+        final int shortcutType = getShortcutType(context);
+        final CharSequence softwareTitle =
+                context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
+                        ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
+                        : R.string.accessibility_shortcut_edit_dialog_title_software);
+
+        List<CharSequence> list = new ArrayList<>();
+        if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) {
+            list.add(softwareTitle);
+        }
+        if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) {
+            final CharSequence hardwareTitle = context.getText(
+                    R.string.accessibility_shortcut_edit_dialog_title_hardware);
+            list.add(hardwareTitle);
         }
 
-        return mDialog;
+        // Show software shortcut if first time to use.
+        if (list.isEmpty()) {
+            list.add(softwareTitle);
+        }
+        final String joinStrings = TextUtils.join(/* delimiter= */", ", list);
+        return AccessibilityUtil.capitalize(joinStrings);
+    }
+
+    @ShortcutType
+    private int getShortcutType(Context context) {
+        return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE);
+    }
+
+    @ShortcutType
+    private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) {
+        return Settings.Secure.getIntForUser(
+                context.getContentResolver(),
+                key, defaultValue, context.getContentResolver().getUserId());
+    }
+
+    private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+        updateShortcutType(true);
+        mShortcutPreference.setSummary(
+                getShortcutTypeSummary(getPrefContext()));
     }
 
     @Override
@@ -147,7 +256,7 @@
 
     @Override
     protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
-        Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? 0 : 1);
+        Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? State.OFF : State.ON);
     }
 
     @Override
@@ -165,14 +274,14 @@
 
     @Override
     public void onSwitchChanged(Switch switchView, boolean isChecked) {
-        Settings.Secure.putInt(getContentResolver(), ENABLED, isChecked ? 1 : 0);
+        Settings.Secure.putInt(getContentResolver(), ENABLED, isChecked ? State.ON : State.OFF);
     }
 
     @Override
     protected void onInstallSwitchBarToggleSwitch() {
         super.onInstallSwitchBarToggleSwitch();
         mSwitchBar.setCheckedInternal(
-                Settings.Secure.getInt(getContentResolver(), ENABLED, 0) == 1);
+                Settings.Secure.getInt(getContentResolver(), ENABLED, State.OFF) == State.ON);
         mSwitchBar.addOnSwitchChangeListener(this);
     }
 
@@ -187,22 +296,31 @@
 
     @Override
     public void onSettingsClicked(ShortcutPreference preference) {
+        mShortcutType = getShortcutType(getPrefContext());
         showDialog(DIALOG_ID_EDIT_SHORTCUT);
     }
 
-    private void initShortcutPreference() {
+    private void initShortcutPreference(Bundle savedInstanceState) {
+        // Restore the Shortcut type
+        if (savedInstanceState != null) {
+            mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT);
+        }
+        if (mShortcutType == ShortcutType.DEFAULT) {
+            mShortcutType = getShortcutType(getPrefContext());
+        }
+
+        // Initial ShortcutPreference widget
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        final ShortcutPreference shortcutPreference = new ShortcutPreference(
+        mShortcutPreference = new ShortcutPreference(
                 preferenceScreen.getContext(), null);
-        final RadioButtonPreference radioButtonPreference = findPreference(RADIOPREFERENCE_KEY);
+        mShortcutPreference.setTitle(R.string.accessibility_shortcut_title);
+        mShortcutPreference.setOnClickListener(this);
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
         // Put the shortcutPreference before radioButtonPreference.
-        shortcutPreference.setOrder(radioButtonPreference.getOrder() - 1);
-        shortcutPreference.setTitle(R.string.accessibility_shortcut_title);
-        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
-        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        final RadioButtonPreference radioButtonPreference = findPreference(PREFERENCE_KEY);
+        mShortcutPreference.setOrder(radioButtonPreference.getOrder() - 1);
+        preferenceScreen.addPreference(mShortcutPreference);
         // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
-        shortcutPreference.setOnClickListener(this);
-        preferenceScreen.addPreference(shortcutPreference);
     }
 
     public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
index 2111f9e..515d80c 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragment.java
@@ -16,15 +16,12 @@
 
 package com.android.settings.accessibility;
 
-import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
-
 import android.app.Dialog;
 import android.app.settings.SettingsEnums;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.res.Resources;
-import android.graphics.Point;
 import android.media.AudioManager;
 import android.media.MediaPlayer;
 import android.media.MediaPlayer.OnPreparedListener;
@@ -32,41 +29,43 @@
 import android.os.Bundle;
 import android.provider.Settings;
 import android.text.TextUtils;
-import android.view.Display;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.view.WindowManager;
+import android.widget.CheckBox;
 import android.widget.ImageView;
 import android.widget.RelativeLayout.LayoutParams;
 import android.widget.Switch;
 import android.widget.VideoView;
 
+import androidx.appcompat.app.AlertDialog;
 import androidx.preference.Preference;
 import androidx.preference.PreferenceScreen;
 import androidx.preference.PreferenceViewHolder;
 
 import com.android.settings.R;
+import com.android.settings.accessibility.AccessibilityUtil.ShortcutType;
 import com.android.settings.widget.SwitchBar;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
 public class ToggleScreenMagnificationPreferenceFragment extends
         ToggleFeaturePreferenceFragment implements SwitchBar.OnSwitchChangeListener,
         ShortcutPreference.OnClickListener {
 
     private static final String SETTINGS_KEY = "screen_magnification_settings";
-    private static final int DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL = 1;
-    private static final int DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL = 2;
-    private static final int DIALOG_ID_EDIT_SHORTCUT = 3;
-
-    private final DialogInterface.OnClickListener mDialogListener =
-            (DialogInterface dialog, int id) -> {
-                if (id == DialogInterface.BUTTON_POSITIVE) {
-                    // TODO(b/142531156): Save the shortcut type preference.
-                }
-            };
-
-    private Dialog mDialog;
+    private static final String EXTRA_SHORTCUT_TYPE = "shortcutType";
+    // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
+    private static final String KEY_SHORTCUT_TYPE = Settings.System.MASTER_MONO;
+    private ShortcutPreference mShortcutPreference;
+    private int mShortcutType = ShortcutType.DEFAULT;
+    private CheckBox mSoftwareTypeCheckBox;
+    private CheckBox mHardwareTypeCheckBox;
+    private CheckBox mTripleTapTypeCheckBox;
 
     protected class VideoPreference extends Preference {
         private ImageView mVideoBackgroundView;
@@ -147,9 +146,6 @@
     protected VideoPreference mVideoPreference;
     protected Preference mConfigWarningPreference;
 
-    private boolean mLaunchFromSuw = false;
-    private boolean mInitialSetting = false;
-
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -185,11 +181,17 @@
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container,
             Bundle savedInstanceState) {
-        initShortcutPreference();
+        initShortcutPreference(savedInstanceState);
         return super.onCreateView(inflater, container, savedInstanceState);
     }
 
     @Override
+    public void onSaveInstanceState(Bundle outState) {
+        outState.putInt(EXTRA_SHORTCUT_TYPE, mShortcutType);
+        super.onSaveInstanceState(outState);
+    }
+
+    @Override
     public void onResume() {
         super.onResume();
 
@@ -204,25 +206,142 @@
     @Override
     public Dialog onCreateDialog(int dialogId) {
         switch (dialogId) {
-            case DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL:
-                mDialog = AccessibilityGestureNavigationTutorial
+            case DialogType.GESTURE_NAVIGATION_TUTORIAL:
+                return AccessibilityGestureNavigationTutorial
                         .showGestureNavigationTutorialDialog(getActivity());
-                break;
-            case DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL:
-                mDialog = AccessibilityGestureNavigationTutorial
+            case DialogType.ACCESSIBILITY_BUTTON_TUTORIAL:
+                return AccessibilityGestureNavigationTutorial
                         .showAccessibilityButtonTutorialDialog(getActivity());
-                break;
-            case DIALOG_ID_EDIT_SHORTCUT:
+            case DialogType.EDIT_SHORTCUT:
                 final CharSequence dialogTitle = getActivity().getString(
                         R.string.accessibility_shortcut_edit_dialog_title_magnification);
-                mDialog = AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
-                        getActivity(), dialogTitle, mDialogListener);
-                break;
-            default:
-                throw new IllegalArgumentException();
+                final AlertDialog dialog =
+                        AccessibilityEditDialogUtils.showMagnificationEditShortcutDialog(
+                                getActivity(), dialogTitle, this::callOnAlertDialogCheckboxClicked);
+                initializeDialogCheckBox(dialog);
+                return dialog;
+        }
+        throw new IllegalArgumentException("Unsupported dialogId " + dialogId);
+    }
+
+    private void initializeDialogCheckBox(AlertDialog dialog) {
+        final View dialogSoftwareView = dialog.findViewById(R.id.software_shortcut);
+        mSoftwareTypeCheckBox = dialogSoftwareView.findViewById(R.id.checkbox);
+        final View dialogHardwareView = dialog.findViewById(R.id.hardware_shortcut);
+        mHardwareTypeCheckBox = dialogHardwareView.findViewById(R.id.checkbox);
+        final View dialogTripleTapView = dialog.findViewById(R.id.triple_tap_shortcut);
+        mTripleTapTypeCheckBox = dialogTripleTapView.findViewById(R.id.checkbox);
+        final View advancedView = dialog.findViewById(R.id.advanced_shortcut);
+        updateAlertDialogCheckState();
+        updateAlertDialogEnableState();
+
+        // Shows the triple tap checkbox directly if clicked.
+        if (mTripleTapTypeCheckBox.isChecked()) {
+            advancedView.setVisibility(View.GONE);
+            dialogTripleTapView.setVisibility(View.VISIBLE);
+        }
+    }
+
+    private void updateAlertDialogCheckState() {
+        updateCheckStatus(mSoftwareTypeCheckBox, ShortcutType.SOFTWARE);
+        updateCheckStatus(mHardwareTypeCheckBox, ShortcutType.HARDWARE);
+        updateCheckStatus(mTripleTapTypeCheckBox, ShortcutType.TRIPLETAP);
+    }
+
+    private void updateAlertDialogEnableState() {
+        if (!mSoftwareTypeCheckBox.isChecked() && !mTripleTapTypeCheckBox.isChecked()) {
+            mHardwareTypeCheckBox.setEnabled(false);
+        } else if (!mHardwareTypeCheckBox.isChecked() && !mTripleTapTypeCheckBox.isChecked()) {
+            mSoftwareTypeCheckBox.setEnabled(false);
+        } else if (!mSoftwareTypeCheckBox.isChecked() && !mHardwareTypeCheckBox.isChecked()) {
+            mTripleTapTypeCheckBox.setEnabled(false);
+        } else {
+            mSoftwareTypeCheckBox.setEnabled(true);
+            mHardwareTypeCheckBox.setEnabled(true);
+            mTripleTapTypeCheckBox.setEnabled(true);
+        }
+    }
+
+    private void updateCheckStatus(CheckBox checkBox, @ShortcutType int type) {
+        checkBox.setChecked((mShortcutType & type) == type);
+        checkBox.setOnClickListener(v -> {
+            updateShortcutType(false);
+            updateAlertDialogEnableState();
+        });
+    }
+
+    private void updateShortcutType(boolean saveToDB) {
+        mShortcutType = ShortcutType.DEFAULT;
+        if (mSoftwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.SOFTWARE;
+        }
+        if (mHardwareTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.HARDWARE;
+        }
+        if (mTripleTapTypeCheckBox.isChecked()) {
+            mShortcutType |= ShortcutType.TRIPLETAP;
+        }
+        if (saveToDB) {
+            setShortcutType(mShortcutType);
+        }
+    }
+
+    private void setSecureIntValue(String key, @ShortcutType int value) {
+        Settings.Secure.putIntForUser(getPrefContext().getContentResolver(),
+                key, value, getPrefContext().getContentResolver().getUserId());
+    }
+
+    private void setShortcutType(@ShortcutType int type) {
+        setSecureIntValue(KEY_SHORTCUT_TYPE, type);
+    }
+
+    private String getShortcutTypeSummary(Context context) {
+        final int shortcutType = getShortcutType(context);
+        final CharSequence softwareTitle =
+                context.getText(AccessibilityUtil.isGestureNavigateEnabled(context)
+                        ? R.string.accessibility_shortcut_edit_dialog_title_software_gesture
+                        : R.string.accessibility_shortcut_edit_dialog_title_software);
+
+        List<CharSequence> list = new ArrayList<>();
+        if ((shortcutType & ShortcutType.SOFTWARE) == ShortcutType.SOFTWARE) {
+            list.add(softwareTitle);
+        }
+        if ((shortcutType & ShortcutType.HARDWARE) == ShortcutType.HARDWARE) {
+            final CharSequence hardwareTitle = context.getText(
+                    R.string.accessibility_shortcut_edit_dialog_title_hardware);
+            list.add(hardwareTitle);
         }
 
-        return mDialog;
+        if ((shortcutType & ShortcutType.TRIPLETAP) == ShortcutType.TRIPLETAP) {
+            final CharSequence tripleTapTitle = context.getText(
+                    R.string.accessibility_shortcut_edit_dialog_title_triple_tap);
+            list.add(tripleTapTitle);
+        }
+
+        // Show software shortcut if first time to use.
+        if (list.isEmpty()) {
+            list.add(softwareTitle);
+        }
+        final String joinStrings = TextUtils.join(/* delimiter= */", ", list);
+        return AccessibilityUtil.capitalize(joinStrings);
+    }
+
+    @ShortcutType
+    private int getShortcutType(Context context) {
+        return getSecureIntValue(context, KEY_SHORTCUT_TYPE, ShortcutType.SOFTWARE);
+    }
+
+    @ShortcutType
+    private int getSecureIntValue(Context context, String key, @ShortcutType int defaultValue) {
+        return Settings.Secure.getIntForUser(
+                context.getContentResolver(),
+                key, defaultValue, context.getContentResolver().getUserId());
+    }
+
+    private void callOnAlertDialogCheckboxClicked(DialogInterface dialog, int which) {
+        updateShortcutType(true);
+        mShortcutPreference.setSummary(
+                getShortcutTypeSummary(getPrefContext()));
     }
 
     @Override
@@ -234,11 +353,11 @@
     @Override
     public int getDialogMetricsCategory(int dialogId) {
         switch (dialogId) {
-            case DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL:
+            case DialogType.GESTURE_NAVIGATION_TUTORIAL:
                 return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_GESTURE_NAVIGATION;
-            case DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL:
+            case DialogType.ACCESSIBILITY_BUTTON_TUTORIAL:
                 return SettingsEnums.DIALOG_TOGGLE_SCREEN_MAGNIFICATION_ACCESSIBILITY_BUTTON;
-            case DIALOG_ID_EDIT_SHORTCUT:
+            case DialogType.EDIT_SHORTCUT:
                 return SettingsEnums.DIALOG_MAGNIFICATION_EDIT_SHORTCUT;
             default:
                 return 0;
@@ -255,8 +374,9 @@
         if (enabled && TextUtils.equals(
                 Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED,
                 preferenceKey)) {
-            showDialog(isGestureNavigateEnabled() ? DIALOG_ID_GESTURE_NAVIGATION_TUTORIAL
-                    : DIALOG_ID_ACCESSIBILITY_BUTTON_TUTORIAL);
+            showDialog(AccessibilityUtil.isGestureNavigateEnabled(getContext())
+                    ? DialogType.GESTURE_NAVIGATION_TUTORIAL
+                    : DialogType.ACCESSIBILITY_BUTTON_TUTORIAL);
         }
         MagnificationPreferenceFragment.setChecked(getContentResolver(), preferenceKey, enabled);
         updateConfigurationWarningIfNeeded();
@@ -293,20 +413,10 @@
 
         if (arguments.containsKey(AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID)) {
             mVideoPreference.setVisible(true);
-            final int resId = arguments.getInt(
-                    AccessibilitySettings.EXTRA_VIDEO_RAW_RESOURCE_ID);
         } else {
             mVideoPreference.setVisible(false);
         }
 
-        if (arguments.containsKey(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW)) {
-            mLaunchFromSuw = arguments.getBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW);
-        }
-
-        if (arguments.containsKey(AccessibilitySettings.EXTRA_CHECKED)) {
-            mInitialSetting = arguments.getBoolean(AccessibilitySettings.EXTRA_CHECKED);
-        }
-
         if (arguments.containsKey(AccessibilitySettings.EXTRA_TITLE_RES)) {
             final int titleRes = arguments.getInt(AccessibilitySettings.EXTRA_TITLE_RES);
             if (titleRes > 0) {
@@ -326,27 +436,30 @@
 
     @Override
     public void onSettingsClicked(ShortcutPreference preference) {
-        showDialog(DIALOG_ID_EDIT_SHORTCUT);
+        mShortcutType = getShortcutType(getPrefContext());
+        showDialog(DialogType.EDIT_SHORTCUT);
     }
 
-    private void initShortcutPreference() {
+    private void initShortcutPreference(Bundle savedInstanceState) {
+        // Restore the Shortcut type
+        if (savedInstanceState != null) {
+            mShortcutType = savedInstanceState.getInt(EXTRA_SHORTCUT_TYPE, ShortcutType.DEFAULT);
+        }
+        if (mShortcutType == ShortcutType.DEFAULT) {
+            mShortcutType = getShortcutType(getPrefContext());
+        }
+
+        // Initial ShortcutPreference widget
         final PreferenceScreen preferenceScreen = getPreferenceScreen();
-        final ShortcutPreference shortcutPreference = new ShortcutPreference(
+        mShortcutPreference = new ShortcutPreference(
                 preferenceScreen.getContext(), null);
+        mShortcutPreference.setTitle(R.string.accessibility_magnification_shortcut_title);
+        mShortcutPreference.setOnClickListener(this);
+        mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext()));
         // Put the shortcutPreference before videoPreference.
-        shortcutPreference.setOrder(mVideoPreference.getOrder() - 1);
-        shortcutPreference.setTitle(R.string.accessibility_magnification_shortcut_title);
-        shortcutPreference.setOnClickListener(this);
-        // TODO(b/142530063): Check the new setting key to decide which summary should be shown.
-        // TODO(b/142530063): Check if gesture mode is on to decide which summary should be shown.
+        mShortcutPreference.setOrder(mVideoPreference.getOrder() - 1);
+        preferenceScreen.addPreference(mShortcutPreference);
         // TODO(b/142530063): Check the new key to decide whether checkbox should be checked.
-        preferenceScreen.addPreference(shortcutPreference);
-    }
-
-    private boolean isGestureNavigateEnabled() {
-        return getContext().getResources().getInteger(
-                com.android.internal.R.integer.config_navBarInteractionMode)
-                == NAV_BAR_MODE_GESTURAL;
     }
 
     private void updateConfigurationWarningIfNeeded() {
@@ -359,11 +472,11 @@
         mConfigWarningPreference.setVisible(warningMessage != null);
     }
 
-    private static int getScreenWidth(Context context) {
-        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        Display display = wm.getDefaultDisplay();
-        Point size = new Point();
-        display.getSize(size);
-        return size.x;
+    @Retention(RetentionPolicy.SOURCE)
+    private @interface DialogType {
+        int GESTURE_NAVIGATION_TUTORIAL = 1;
+        int ACCESSIBILITY_BUTTON_TUTORIAL = 2;
+        int EDIT_SHORTCUT = 3;
     }
+
 }
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
index 5a04143..b9b8b87 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardLoader.java
@@ -49,7 +49,7 @@
 public class ContextualCardLoader extends AsyncLoaderCompat<List<ContextualCard>> {
 
     @VisibleForTesting
-    static final int DEFAULT_CARD_COUNT = 2;
+    static final int DEFAULT_CARD_COUNT = 3;
     static final int CARD_CONTENT_LOADER_ID = 1;
 
     private static final String TAG = "ContextualCardLoader";
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityUtilTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityUtilTest.java
index 27db431..2ccfd05 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityUtilTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityUtilTest.java
@@ -54,6 +54,16 @@
     }
 
     @Test
+    public void capitalize_shouldReturnCapitalizedString() {
+        assertThat(AccessibilityUtil.capitalize(null)).isNull();
+        assertThat(AccessibilityUtil.capitalize("")).isEmpty();
+        assertThat(AccessibilityUtil.capitalize("Hans")).isEqualTo("Hans");
+        assertThat(AccessibilityUtil.capitalize("hans")).isEqualTo("Hans");
+        assertThat(AccessibilityUtil.capitalize(",hans")).isEqualTo(",hans");
+        assertThat(AccessibilityUtil.capitalize("Hans, Hans")).isEqualTo("Hans, hans");
+    }
+
+    @Test
     public void getSummary_hasValueAndEqualsToOne_shouldReturnOnString() {
         Settings.Secure.putInt(mContext.getContentResolver(), SECURE_TEST_KEY, ON);
 
@@ -90,7 +100,6 @@
 
         assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
                 AccessibilityUtil.AccessibilityServiceFragmentType.LEGACY);
-
     }
 
     @Test
@@ -102,7 +111,6 @@
 
         assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
                 AccessibilityUtil.AccessibilityServiceFragmentType.INVISIBLE);
-
     }
 
     @Test
@@ -114,7 +122,6 @@
 
         assertThat(AccessibilityUtil.getAccessibilityServiceFragmentType(info)).isEqualTo(
                 AccessibilityUtil.AccessibilityServiceFragmentType.INTUITIVE);
-
     }