Convert a11y shortcut edit screen to a full screen.
Bug: 300302098 Flag: adb shell device_config put accessibility com.android.settings.accessibility.edit_shortcuts_in_full_screen true Test: manual Test: atest com.android.settings.accessibility.shortcuts Change-Id: I0b5e367fed962ff01036122ce7ff32a8ae47fbc3
This commit is contained in:
@@ -44,6 +44,7 @@ import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
|
||||
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
|
||||
import com.android.settings.dashboard.RestrictedDashboardFragment;
|
||||
import com.android.settings.utils.LocaleUtils;
|
||||
|
||||
@@ -251,7 +252,17 @@ public abstract class AccessibilityShortcutPreferenceFragment extends Restricted
|
||||
|
||||
@Override
|
||||
public void onSettingsClicked(ShortcutPreference preference) {
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
if (Flags.editShortcutsInFullScreen()) {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
getContext(),
|
||||
getMetricsCategory(),
|
||||
getShortcutTitle(),
|
||||
getComponentName(),
|
||||
getIntent()
|
||||
);
|
||||
} else {
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
/**
|
||||
* An interface denoting a preference is expandable
|
||||
*/
|
||||
public interface ExpandablePreference {
|
||||
|
||||
/**
|
||||
* Set the expandable state of the preference
|
||||
*/
|
||||
void setExpanded(boolean expanded);
|
||||
|
||||
/**
|
||||
* Returns if the preference is currently expanded.
|
||||
*/
|
||||
boolean isExpanded();
|
||||
}
|
||||
@@ -48,6 +48,7 @@ import androidx.annotation.Nullable;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
|
||||
import com.android.settingslib.accessibility.AccessibilityUtils;
|
||||
|
||||
import java.util.List;
|
||||
@@ -539,7 +540,17 @@ public class ToggleAccessibilityServicePreferenceFragment extends
|
||||
|
||||
private void onAllowButtonFromShortcutClicked() {
|
||||
mIsDialogShown.set(false);
|
||||
showPopupDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
if (Flags.editShortcutsInFullScreen()) {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
getContext(),
|
||||
getMetricsCategory(),
|
||||
getShortcutTitle(),
|
||||
mComponentName,
|
||||
getIntent()
|
||||
);
|
||||
} else {
|
||||
showPopupDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
|
||||
if (mWarningDialog != null) {
|
||||
mWarningDialog.dismiss();
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.flags.Flags;
|
||||
import com.android.settings.utils.LocaleUtils;
|
||||
@@ -832,7 +833,13 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment
|
||||
|
||||
@Override
|
||||
public void onSettingsClicked(ShortcutPreference preference) {
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
if (com.android.settings.accessibility.Flags.editShortcutsInFullScreen()) {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
requireContext(), getMetricsCategory(), getShortcutTitle(),
|
||||
mComponentName, getIntent());
|
||||
} else {
|
||||
showDialog(DialogEnums.EDIT_SHORTCUT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.settings.accessibility;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
|
||||
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
|
||||
@@ -55,6 +56,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
|
||||
import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType;
|
||||
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
|
||||
import com.android.settings.utils.LocaleUtils;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
@@ -584,7 +586,16 @@ public class ToggleScreenMagnificationPreferenceFragment extends
|
||||
|
||||
@Override
|
||||
public void onSettingsClicked(ShortcutPreference preference) {
|
||||
showDialog(DialogEnums.MAGNIFICATION_EDIT_SHORTCUT);
|
||||
if (com.android.settings.accessibility.Flags.editShortcutsInFullScreen()) {
|
||||
EditShortcutsPreferenceFragment.showEditShortcutScreen(
|
||||
requireContext(),
|
||||
getMetricsCategory(),
|
||||
getShortcutTitle(),
|
||||
MAGNIFICATION_COMPONENT_NAME,
|
||||
getIntent());
|
||||
} else {
|
||||
showDialog(DialogEnums.MAGNIFICATION_EDIT_SHORTCUT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.android.settings.accessibility.ExpandablePreference;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A preference controller that controls an expandable preference that wraps
|
||||
* the advanced shortcut options.
|
||||
*/
|
||||
public class AdvancedShortcutsPreferenceController extends ShortcutOptionPreferenceController
|
||||
implements ExpandablePreference {
|
||||
|
||||
private boolean mIsExpanded = false;
|
||||
|
||||
public AdvancedShortcutsPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isChecked() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (!isExpanded() && isShortcutAvailable()) {
|
||||
// "Advanced" is available when the user hasn't clicked on it
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpanded(boolean expanded) {
|
||||
mIsExpanded = expanded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpanded() {
|
||||
return mIsExpanded;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
// Only Magnification has advanced shortcut options.
|
||||
Set<String> shortcutTargets = getShortcutTargets();
|
||||
return shortcutTargets.size() == 1
|
||||
&& shortcutTargets.contains(MAGNIFICATION_CONTROLLER_NAME);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED;
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.SetupWizardUtils;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settingslib.core.AbstractPreferenceController;
|
||||
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A screen show various accessibility shortcut options for the given a11y feature
|
||||
*/
|
||||
public class EditShortcutsPreferenceFragment extends DashboardFragment {
|
||||
private static final String TAG = "EditShortcutsPreferenceFragment";
|
||||
|
||||
@VisibleForTesting
|
||||
static final String ARG_KEY_SHORTCUT_TARGETS = "targets";
|
||||
@VisibleForTesting
|
||||
static final String SAVED_STATE_IS_EXPANDED = "isExpanded";
|
||||
private ContentObserver mSettingsObserver;
|
||||
|
||||
private static final Uri VOLUME_KEYS_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_SHORTCUT_TARGET_SERVICE);
|
||||
private static final Uri BUTTON_SHORTCUT_MODE_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_BUTTON_MODE);
|
||||
private static final Uri BUTTON_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_BUTTON_TARGETS);
|
||||
|
||||
private static final Uri TRIPLE_TAP_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED);
|
||||
private static final Uri TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING =
|
||||
Settings.Secure.getUriFor(ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED);
|
||||
|
||||
@VisibleForTesting
|
||||
static final Uri[] SHORTCUT_SETTINGS = {
|
||||
VOLUME_KEYS_SHORTCUT_SETTING,
|
||||
BUTTON_SHORTCUT_MODE_SETTING,
|
||||
BUTTON_SHORTCUT_SETTING,
|
||||
TRIPLE_TAP_SHORTCUT_SETTING,
|
||||
TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING,
|
||||
};
|
||||
|
||||
private Set<String> mShortcutTargets;
|
||||
|
||||
@Nullable
|
||||
private AccessibilityManager.TouchExplorationStateChangeListener
|
||||
mTouchExplorationStateChangeListener;
|
||||
|
||||
|
||||
/**
|
||||
* Helper method to show the edit shortcut screen
|
||||
*/
|
||||
public static void showEditShortcutScreen(
|
||||
Context context, int metricsCategory, CharSequence screenTitle,
|
||||
ComponentName target, Intent fromIntent) {
|
||||
Bundle args = new Bundle();
|
||||
|
||||
if (MAGNIFICATION_COMPONENT_NAME.equals(target)) {
|
||||
// We can remove this branch once b/147990389 is completed
|
||||
args.putStringArray(
|
||||
ARG_KEY_SHORTCUT_TARGETS, new String[]{MAGNIFICATION_CONTROLLER_NAME});
|
||||
} else {
|
||||
args.putStringArray(
|
||||
ARG_KEY_SHORTCUT_TARGETS, new String[]{target.flattenToString()});
|
||||
}
|
||||
Intent toIntent = new Intent();
|
||||
if (fromIntent != null) {
|
||||
SetupWizardUtils.copySetupExtras(fromIntent, toIntent);
|
||||
}
|
||||
|
||||
new SubSettingLauncher(context)
|
||||
.setDestination(EditShortcutsPreferenceFragment.class.getName())
|
||||
.setExtras(toIntent.getExtras())
|
||||
.setArguments(args)
|
||||
.setSourceMetricsCategory(metricsCategory)
|
||||
.setTitleText(screenTitle)
|
||||
.launch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
initializeArguments();
|
||||
initializePreferenceControllerArguments();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState != null) {
|
||||
boolean isExpanded = savedInstanceState.getBoolean(SAVED_STATE_IS_EXPANDED);
|
||||
if (isExpanded) {
|
||||
onExpanded();
|
||||
}
|
||||
}
|
||||
mSettingsObserver = new ContentObserver(new Handler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
if (VOLUME_KEYS_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshPreferenceController(VolumeKeysShortcutOptionController.class);
|
||||
} else if (BUTTON_SHORTCUT_MODE_SETTING.equals(uri)
|
||||
|| BUTTON_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshSoftwareShortcutControllers();
|
||||
} else if (TRIPLE_TAP_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshPreferenceController(TripleTapShortcutOptionController.class);
|
||||
} else if (TWO_FINGERS_DOUBLE_TAP_SHORTCUT_SETTING.equals(uri)) {
|
||||
refreshPreferenceController(TwoFingersDoubleTapShortcutOptionController.class);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
registerSettingsObserver();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
mTouchExplorationStateChangeListener = isTouchExplorationEnabled ->
|
||||
refreshPreferenceController(GestureShortcutOptionController.class);
|
||||
|
||||
final AccessibilityManager am = getSystemService(
|
||||
AccessibilityManager.class);
|
||||
am.addTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if (mTouchExplorationStateChangeListener != null) {
|
||||
final AccessibilityManager am = getSystemService(
|
||||
AccessibilityManager.class);
|
||||
am.removeTouchExplorationStateChangeListener(mTouchExplorationStateChangeListener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putBoolean(
|
||||
SAVED_STATE_IS_EXPANDED,
|
||||
use(AdvancedShortcutsPreferenceController.class).isExpanded());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
unregisterSettingsObserver();
|
||||
}
|
||||
|
||||
private void registerSettingsObserver() {
|
||||
if (mSettingsObserver != null) {
|
||||
for (Uri uri : SHORTCUT_SETTINGS) {
|
||||
getContentResolver().registerContentObserver(
|
||||
uri, /* notifyForDescendants= */ false, mSettingsObserver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void unregisterSettingsObserver() {
|
||||
if (mSettingsObserver != null) {
|
||||
getContentResolver().unregisterContentObserver(mSettingsObserver);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeArguments() {
|
||||
Bundle args = getArguments();
|
||||
if (args == null || args.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
EditShortcutsPreferenceFragment.class.getSimpleName()
|
||||
+ " requires non-empty shortcut targets");
|
||||
}
|
||||
|
||||
String[] targets = args.getStringArray(ARG_KEY_SHORTCUT_TARGETS);
|
||||
if (targets == null) {
|
||||
throw new IllegalArgumentException(
|
||||
EditShortcutsPreferenceFragment.class.getSimpleName()
|
||||
+ " requires non-empty shortcut targets");
|
||||
}
|
||||
|
||||
mShortcutTargets = Set.of(targets);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.accessibility_edit_shortcuts;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceTreeClick(Preference preference) {
|
||||
if (getString(R.string.accessibility_shortcuts_advanced_collapsed)
|
||||
.equals(preference.getKey())) {
|
||||
onExpanded();
|
||||
// log here since calling super.onPreferenceTreeClick will be skipped
|
||||
writePreferenceClickMetric(preference);
|
||||
return true;
|
||||
}
|
||||
return super.onPreferenceTreeClick(preference);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void initializePreferenceControllerArguments() {
|
||||
boolean isInSuw = WizardManagerHelper.isAnySetupWizard(getIntent());
|
||||
|
||||
getPreferenceControllers()
|
||||
.stream()
|
||||
.flatMap(Collection::stream)
|
||||
.filter(
|
||||
controller -> controller instanceof ShortcutOptionPreferenceController)
|
||||
.forEach(controller -> {
|
||||
ShortcutOptionPreferenceController shortcutOptionPreferenceController =
|
||||
(ShortcutOptionPreferenceController) controller;
|
||||
shortcutOptionPreferenceController.setShortcutTargets(mShortcutTargets);
|
||||
shortcutOptionPreferenceController.setInSetupWizard(isInSuw);
|
||||
});
|
||||
}
|
||||
|
||||
private void onExpanded() {
|
||||
AdvancedShortcutsPreferenceController advanced =
|
||||
use(AdvancedShortcutsPreferenceController.class);
|
||||
advanced.setExpanded(true);
|
||||
|
||||
TripleTapShortcutOptionController tripleTapShortcutOptionController =
|
||||
use(TripleTapShortcutOptionController.class);
|
||||
tripleTapShortcutOptionController.setExpanded(true);
|
||||
|
||||
refreshPreferenceController(AdvancedShortcutsPreferenceController.class);
|
||||
refreshPreferenceController(TripleTapShortcutOptionController.class);
|
||||
}
|
||||
|
||||
private void refreshPreferenceController(
|
||||
Class<? extends AbstractPreferenceController> controllerClass) {
|
||||
AbstractPreferenceController controller = use(controllerClass);
|
||||
if (controller != null) {
|
||||
controller.displayPreference(getPreferenceScreen());
|
||||
if (!TextUtils.isEmpty(controller.getPreferenceKey())) {
|
||||
controller.updateState(findPreference(controller.getPreferenceKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshSoftwareShortcutControllers() {
|
||||
// Gesture
|
||||
refreshPreferenceController(GestureShortcutOptionController.class);
|
||||
|
||||
// FAB
|
||||
refreshPreferenceController(FloatingButtonShortcutOptionController.class);
|
||||
|
||||
// A11y Nav Button
|
||||
refreshPreferenceController(NavButtonShortcutOptionController.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
/**
|
||||
* A controller handles displaying the floating action button shortcut option preference and
|
||||
* configuring the shortcut.
|
||||
*/
|
||||
public class FloatingButtonShortcutOptionController
|
||||
extends SoftwareShortcutOptionPreferenceController {
|
||||
|
||||
public FloatingButtonShortcutOptionController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference instanceof ShortcutOptionPreference shortcutOptionPreference) {
|
||||
shortcutOptionPreference.setTitle(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_software);
|
||||
shortcutOptionPreference.setIntroImageResId(
|
||||
R.drawable.a11y_shortcut_type_software_floating);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
return AccessibilityUtil.isFloatingMenuEnabled(mContext);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
if (isInSetupWizard()) {
|
||||
return null;
|
||||
}
|
||||
return new SpannableStringBuilder().append(getCustomizeAccessibilityButtonLink());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
/**
|
||||
* A controller handles displaying the gesture shortcut option preference and
|
||||
* configuring the shortcut.
|
||||
*/
|
||||
public class GestureShortcutOptionController extends SoftwareShortcutOptionPreferenceController {
|
||||
|
||||
public GestureShortcutOptionController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference instanceof ShortcutOptionPreference shortcutOptionPreference) {
|
||||
shortcutOptionPreference.setTitle(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_software_by_gesture);
|
||||
|
||||
int resId = AccessibilityUtil.isTouchExploreEnabled(mContext)
|
||||
? R.drawable.a11y_shortcut_type_software_gesture_talkback
|
||||
: R.drawable.a11y_shortcut_type_software_gesture;
|
||||
shortcutOptionPreference.setIntroImageResId(resId);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
return !isInSetupWizard()
|
||||
&& !AccessibilityUtil.isFloatingMenuEnabled(mContext)
|
||||
&& AccessibilityUtil.isGestureNavigateEnabled(mContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
final int resId = AccessibilityUtil.isTouchExploreEnabled(mContext)
|
||||
? R.string.accessibility_shortcut_edit_dialog_summary_software_gesture_talkback
|
||||
: R.string.accessibility_shortcut_edit_dialog_summary_software_gesture;
|
||||
sb.append(mContext.getText(resId));
|
||||
sb.append("\n\n");
|
||||
sb.append(getCustomizeAccessibilityButtonLink());
|
||||
|
||||
return sb;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.style.ImageSpan;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
/**
|
||||
* A controller handles displaying the nav button shortcut option preference and
|
||||
* configuring the shortcut.
|
||||
*/
|
||||
public class NavButtonShortcutOptionController extends SoftwareShortcutOptionPreferenceController {
|
||||
|
||||
public NavButtonShortcutOptionController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference instanceof ShortcutOptionPreference shortcutOptionPreference) {
|
||||
shortcutOptionPreference.setTitle(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_software);
|
||||
shortcutOptionPreference.setIntroImageResId(R.drawable.a11y_shortcut_type_software);
|
||||
shortcutOptionPreference.setSummaryProvider(
|
||||
new Preference.SummaryProvider<ShortcutOptionPreference>() {
|
||||
@Override
|
||||
public CharSequence provideSummary(
|
||||
@NonNull ShortcutOptionPreference preference) {
|
||||
return getSummary(preference.getSummaryTextLineHeight());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
return !AccessibilityUtil.isFloatingMenuEnabled(mContext)
|
||||
&& !AccessibilityUtil.isGestureNavigateEnabled(mContext);
|
||||
}
|
||||
|
||||
private CharSequence getSummary(int lineHeight) {
|
||||
final SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
sb.append(getSummaryStringWithIcon(lineHeight));
|
||||
|
||||
if (!isInSetupWizard()) {
|
||||
sb.append("\n\n");
|
||||
sb.append(getCustomizeAccessibilityButtonLink());
|
||||
}
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
private SpannableString getSummaryStringWithIcon(int lineHeight) {
|
||||
final String summary = mContext
|
||||
.getString(R.string.accessibility_shortcut_edit_dialog_summary_software);
|
||||
final SpannableString spannableMessage = SpannableString.valueOf(summary);
|
||||
|
||||
// Icon
|
||||
final int indexIconStart = summary.indexOf("%s");
|
||||
final int indexIconEnd = indexIconStart + 2;
|
||||
final Drawable icon = mContext.getDrawable(R.drawable.ic_accessibility_new);
|
||||
final ImageSpan imageSpan = new ImageSpan(icon);
|
||||
imageSpan.setContentDescription("");
|
||||
icon.setBounds(
|
||||
/* left= */ 0, /* top= */ 0, /* right= */ lineHeight, /* bottom= */ lineHeight);
|
||||
spannableMessage.setSpan(
|
||||
imageSpan, indexIconStart, indexIconEnd,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
return spannableMessage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RawRes;
|
||||
import androidx.preference.CheckBoxPreference;
|
||||
import androidx.preference.PreferenceViewHolder;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.widget.LottieColorUtils;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieDrawable;
|
||||
|
||||
/**
|
||||
* A preference represents an accessibility shortcut option with a checkbox and a tutorial image
|
||||
*/
|
||||
public class ShortcutOptionPreference extends CheckBoxPreference {
|
||||
|
||||
private static final String TAG = "ShortcutOptionPreference";
|
||||
|
||||
@DrawableRes
|
||||
private int mIntroImageResId = Resources.ID_NULL;
|
||||
@RawRes
|
||||
private int mIntroImageRawResId = Resources.ID_NULL;
|
||||
|
||||
private int mSummaryTextLineHeight;
|
||||
|
||||
public ShortcutOptionPreference(
|
||||
@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init();
|
||||
}
|
||||
|
||||
public ShortcutOptionPreference(@NonNull Context context, @Nullable AttributeSet attrs,
|
||||
int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
public ShortcutOptionPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init();
|
||||
}
|
||||
|
||||
public ShortcutOptionPreference(@NonNull Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
setLayoutResource(R.layout.accessibility_shortcut_option_checkable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
|
||||
super.onBindViewHolder(holder);
|
||||
|
||||
if (mIntroImageResId == Resources.ID_NULL && mIntroImageRawResId == Resources.ID_NULL) {
|
||||
holder.findViewById(R.id.image).setVisibility(View.GONE);
|
||||
} else {
|
||||
holder.findViewById(R.id.image).setVisibility(View.VISIBLE);
|
||||
LottieAnimationView imageView = holder.itemView.findViewById(R.id.image);
|
||||
|
||||
if (mIntroImageRawResId != Resources.ID_NULL) {
|
||||
imageView.setFailureListener(result ->
|
||||
Log.w(TAG,
|
||||
"Invalid image raw resource id: "
|
||||
+ getContext().getResources()
|
||||
.getResourceEntryName(mIntroImageRawResId),
|
||||
result));
|
||||
imageView.setAnimation(mIntroImageRawResId);
|
||||
imageView.setRepeatCount(LottieDrawable.INFINITE);
|
||||
LottieColorUtils.applyDynamicColors(getContext(), imageView);
|
||||
imageView.playAnimation();
|
||||
} else {
|
||||
imageView.setImageResource(mIntroImageResId);
|
||||
}
|
||||
}
|
||||
|
||||
final TextView summaryView = (TextView) holder.findViewById(android.R.id.summary);
|
||||
if (summaryView != null) {
|
||||
mSummaryTextLineHeight = summaryView.getLineHeight();
|
||||
summaryView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
}
|
||||
|
||||
syncSummaryView(holder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the introduction image for this preference with a drawable resource ID.
|
||||
*/
|
||||
public void setIntroImageResId(@DrawableRes int introImageResId) {
|
||||
if (introImageResId != mIntroImageResId) {
|
||||
mIntroImageResId = introImageResId;
|
||||
mIntroImageRawResId = Resources.ID_NULL;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the introduction image for this preference with a raw resource ID for an animated image.
|
||||
*/
|
||||
public void setIntroImageRawResId(@RawRes int introImageRawResId) {
|
||||
if (introImageRawResId != mIntroImageRawResId) {
|
||||
mIntroImageRawResId = introImageRawResId;
|
||||
mIntroImageResId = Resources.ID_NULL;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
public int getSummaryTextLineHeight() {
|
||||
return mSummaryTextLineHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.preference.Preference;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.internal.accessibility.util.ShortcutUtils;
|
||||
import com.android.internal.util.Preconditions;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A base preference controller for {@link ShortcutOptionPreference}
|
||||
*/
|
||||
public abstract class ShortcutOptionPreferenceController extends BasePreferenceController
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
private Set<String> mShortcutTargets = Collections.emptySet();
|
||||
private boolean mIsInSetupWizard;
|
||||
|
||||
public ShortcutOptionPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateState(Preference preference) {
|
||||
super.updateState(preference);
|
||||
if (getPreferenceKey().equals(preference.getKey())
|
||||
&& preference instanceof ShortcutOptionPreference) {
|
||||
((ShortcutOptionPreference) preference).setChecked(isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (isShortcutAvailable()) {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the targets (i.e. a11y features) to be configured with the a11y shortcut option.
|
||||
* <p>
|
||||
* Note: the shortcutTargets cannot be empty, since the edit a11y shortcut option
|
||||
* is meant to configure the shortcut options for an a11y feature.
|
||||
* </>
|
||||
*
|
||||
* @param shortcutTargets the a11y features, like color correction, Talkback, etc.
|
||||
* @throws NullPointerException if the {@code shortcutTargets} was {@code null}
|
||||
* @throws IllegalArgumentException if the {@code shortcutTargets} was empty
|
||||
*/
|
||||
public void setShortcutTargets(Set<String> shortcutTargets) {
|
||||
Preconditions.checkCollectionNotEmpty(shortcutTargets, /* valueName= */ "a11y targets");
|
||||
|
||||
this.mShortcutTargets = shortcutTargets;
|
||||
}
|
||||
|
||||
public void setInSetupWizard(boolean isInSetupWizard) {
|
||||
this.mIsInSetupWizard = isInSetupWizard;
|
||||
}
|
||||
|
||||
protected Set<String> getShortcutTargets() {
|
||||
return mShortcutTargets;
|
||||
}
|
||||
|
||||
protected boolean isInSetupWizard() {
|
||||
return mIsInSetupWizard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onPreferenceChange(@NonNull Preference preference, Object newValue) {
|
||||
enableShortcutForTargets((Boolean) newValue);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ShortcutConstants.UserShortcutType
|
||||
protected int getShortcutType() {
|
||||
return ShortcutConstants.UserShortcutType.DEFAULT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the shortcut is associated to the targets
|
||||
*/
|
||||
protected boolean isChecked() {
|
||||
Set<String> targets = ShortcutUtils.getShortcutTargetsFromSettings(
|
||||
mContext, getShortcutType(), UserHandle.myUserId());
|
||||
|
||||
return !targets.isEmpty() && targets.containsAll(getShortcutTargets());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable or disable the shortcut for the given accessibility features.
|
||||
*/
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
Set<String> shortcutTargets = getShortcutTargets();
|
||||
@ShortcutConstants.UserShortcutType int shortcutType = getShortcutType();
|
||||
|
||||
if (enable) {
|
||||
for (String target : shortcutTargets) {
|
||||
ShortcutUtils.optInValueToSettings(mContext, shortcutType, target);
|
||||
}
|
||||
} else {
|
||||
for (String target : shortcutTargets) {
|
||||
ShortcutUtils.optOutValueFromSettings(mContext, shortcutType, target);
|
||||
}
|
||||
}
|
||||
ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState(
|
||||
mContext, shortcutTargets, UserHandle.myUserId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user can associate a shortcut to the targets
|
||||
*/
|
||||
protected abstract boolean isShortcutAvailable();
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityButtonFragment;
|
||||
import com.android.settings.accessibility.FloatingMenuSizePreferenceController;
|
||||
import com.android.settings.core.SubSettingLauncher;
|
||||
import com.android.settings.utils.AnnotationSpan;
|
||||
|
||||
/**
|
||||
* A base controller for the preference controller of software shortcuts.
|
||||
*/
|
||||
public abstract class SoftwareShortcutOptionPreferenceController
|
||||
extends ShortcutOptionPreferenceController {
|
||||
|
||||
public SoftwareShortcutOptionPreferenceController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@ShortcutConstants.UserShortcutType
|
||||
@Override
|
||||
protected int getShortcutType() {
|
||||
return ShortcutConstants.UserShortcutType.SOFTWARE;
|
||||
}
|
||||
|
||||
private boolean isMagnificationInTargets() {
|
||||
return getShortcutTargets().contains(MAGNIFICATION_CONTROLLER_NAME);
|
||||
}
|
||||
|
||||
protected CharSequence getCustomizeAccessibilityButtonLink() {
|
||||
final View.OnClickListener linkListener = v -> new SubSettingLauncher(mContext)
|
||||
.setDestination(AccessibilityButtonFragment.class.getName())
|
||||
.setSourceMetricsCategory(getMetricsCategory())
|
||||
.launch();
|
||||
final AnnotationSpan.LinkInfo linkInfo = new AnnotationSpan.LinkInfo(
|
||||
AnnotationSpan.LinkInfo.DEFAULT_ANNOTATION, linkListener);
|
||||
return AnnotationSpan.linkify(
|
||||
mContext.getText(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_software_floating),
|
||||
linkInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
super.enableShortcutForTargets(enable);
|
||||
|
||||
if (enable) {
|
||||
// Update the A11y FAB size to large when the Magnification shortcut is enabled
|
||||
// and the user hasn't changed the floating button size
|
||||
if (isMagnificationInTargets()
|
||||
&& Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
|
||||
FloatingMenuSizePreferenceController.Size.UNKNOWN)
|
||||
== FloatingMenuSizePreferenceController.Size.UNKNOWN) {
|
||||
Settings.Secure.putInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE,
|
||||
FloatingMenuSizePreferenceController.Size.LARGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
|
||||
import android.content.Context;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
import com.android.settings.accessibility.ExpandablePreference;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A controller handles displaying the triple tap shortcut option preference and
|
||||
* configuring the shortcut.
|
||||
*/
|
||||
public class TripleTapShortcutOptionController extends ShortcutOptionPreferenceController
|
||||
implements ExpandablePreference {
|
||||
|
||||
private boolean mIsExpanded = false;
|
||||
|
||||
public TripleTapShortcutOptionController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference instanceof ShortcutOptionPreference shortcutOptionPreference) {
|
||||
shortcutOptionPreference.setTitle(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_triple_tap);
|
||||
String summary = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_triple_tap);
|
||||
// Format the number '3' in the summary.
|
||||
final Object[] arguments = {3};
|
||||
summary = MessageFormat.format(summary, arguments);
|
||||
|
||||
shortcutOptionPreference.setSummary(summary);
|
||||
shortcutOptionPreference.setIntroImageRawResId(
|
||||
R.raw.a11y_shortcut_type_triple_tap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
if (isExpanded() && isShortcutAvailable()) {
|
||||
return AVAILABLE_UNSEARCHABLE;
|
||||
}
|
||||
return CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
@ShortcutConstants.UserShortcutType
|
||||
@Override
|
||||
protected int getShortcutType() {
|
||||
return ShortcutConstants.UserShortcutType.TRIPLETAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExpanded(boolean expanded) {
|
||||
mIsExpanded = expanded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExpanded() {
|
||||
return mIsExpanded;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
Set<String> shortcutTargets = getShortcutTargets();
|
||||
return shortcutTargets.size() == 1
|
||||
&& shortcutTargets.contains(MAGNIFICATION_CONTROLLER_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isChecked() {
|
||||
return Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
|
||||
AccessibilityUtil.State.OFF) == AccessibilityUtil.State.ON;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
Settings.Secure.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED,
|
||||
enable ? AccessibilityUtil.State.ON : AccessibilityUtil.State.OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
|
||||
import android.content.Context;
|
||||
import android.icu.text.MessageFormat;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.server.accessibility.Flags;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A controller handles displaying the two fingers double tap shortcut option preference and
|
||||
* configuring the shortcut.
|
||||
*/
|
||||
public class TwoFingersDoubleTapShortcutOptionController
|
||||
extends ShortcutOptionPreferenceController {
|
||||
|
||||
public TwoFingersDoubleTapShortcutOptionController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@ShortcutConstants.UserShortcutType
|
||||
@Override
|
||||
protected int getShortcutType() {
|
||||
return ShortcutConstants.UserShortcutType.TRIPLETAP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference instanceof ShortcutOptionPreference shortcutOptionPreference) {
|
||||
// TODO (b/306153204): Update shortcut string and image when UX provides them
|
||||
shortcutOptionPreference.setTitle(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_two_finger_double_tap);
|
||||
String summary = mContext.getString(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_two_finger_double_tap);
|
||||
// Format the number '2' in the summary.
|
||||
final Object[] arguments = {2};
|
||||
summary = MessageFormat.format(summary, arguments);
|
||||
|
||||
shortcutOptionPreference.setSummary(summary);
|
||||
shortcutOptionPreference.setIntroImageRawResId(
|
||||
R.raw.a11y_shortcut_type_triple_tap);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
if (!Flags.enableMagnificationMultipleFingerMultipleTapGesture()) {
|
||||
return false;
|
||||
}
|
||||
// Only Magnification has two fingers triple tap shortcut option.
|
||||
Set<String> shortcutTargets = getShortcutTargets();
|
||||
return shortcutTargets.size() == 1
|
||||
&& shortcutTargets.contains(MAGNIFICATION_CONTROLLER_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isChecked() {
|
||||
return Settings.Secure.getInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
|
||||
AccessibilityUtil.State.OFF) == AccessibilityUtil.State.ON;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
Settings.Secure.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_TWO_FINGER_TRIPLE_TAP_ENABLED,
|
||||
enable ? AccessibilityUtil.State.ON : AccessibilityUtil.State.OFF);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.accessibility.shortcuts;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
|
||||
import com.android.internal.accessibility.common.ShortcutConstants;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.accessibility.AccessibilityUtil;
|
||||
|
||||
/**
|
||||
* A controller handles displaying the volume keys shortcut option preference and
|
||||
* configuring the shortcut.
|
||||
*/
|
||||
public class VolumeKeysShortcutOptionController extends ShortcutOptionPreferenceController {
|
||||
|
||||
public VolumeKeysShortcutOptionController(
|
||||
Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
@ShortcutConstants.UserShortcutType
|
||||
@Override
|
||||
protected int getShortcutType() {
|
||||
return ShortcutConstants.UserShortcutType.HARDWARE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void displayPreference(PreferenceScreen screen) {
|
||||
super.displayPreference(screen);
|
||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||
if (preference instanceof ShortcutOptionPreference shortcutOptionPreference) {
|
||||
shortcutOptionPreference.setTitle(
|
||||
R.string.accessibility_shortcut_edit_dialog_title_hardware);
|
||||
shortcutOptionPreference.setSummary(
|
||||
R.string.accessibility_shortcut_edit_dialog_summary_hardware);
|
||||
shortcutOptionPreference.setIntroImageResId(
|
||||
R.drawable.a11y_shortcut_type_hardware);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isShortcutAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void enableShortcutForTargets(boolean enable) {
|
||||
super.enableShortcutForTargets(enable);
|
||||
if (enable) {
|
||||
AccessibilityUtil.skipVolumeShortcutDialogTimeoutRestriction(mContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user