1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.accessibility.shortcuts; 18 19 import android.content.Context; 20 import android.os.UserHandle; 21 import android.view.accessibility.AccessibilityManager; 22 import android.view.accessibility.Flags; 23 24 import androidx.annotation.NonNull; 25 import androidx.preference.Preference; 26 27 import com.android.internal.accessibility.common.ShortcutConstants; 28 import com.android.internal.accessibility.util.ShortcutUtils; 29 import com.android.internal.util.Preconditions; 30 import com.android.settings.core.BasePreferenceController; 31 32 import java.util.Collections; 33 import java.util.Set; 34 35 /** 36 * A base preference controller for {@link ShortcutOptionPreference} 37 */ 38 public abstract class ShortcutOptionPreferenceController extends BasePreferenceController 39 implements Preference.OnPreferenceChangeListener { 40 private Set<String> mShortcutTargets = Collections.emptySet(); 41 private boolean mIsInSetupWizard; 42 ShortcutOptionPreferenceController(Context context, String preferenceKey)43 public ShortcutOptionPreferenceController(Context context, String preferenceKey) { 44 super(context, preferenceKey); 45 } 46 47 @Override updateState(Preference preference)48 public void updateState(Preference preference) { 49 super.updateState(preference); 50 if (getPreferenceKey().equals(preference.getKey()) 51 && preference instanceof ShortcutOptionPreference) { 52 ((ShortcutOptionPreference) preference).setChecked(isChecked()); 53 } 54 } 55 56 @Override getAvailabilityStatus()57 public int getAvailabilityStatus() { 58 if (isShortcutAvailable()) { 59 return AVAILABLE_UNSEARCHABLE; 60 } 61 return CONDITIONALLY_UNAVAILABLE; 62 } 63 64 /** 65 * Set the targets (i.e. a11y features) to be configured with the a11y shortcut option. 66 * <p> 67 * Note: the shortcutTargets cannot be empty, since the edit a11y shortcut option 68 * is meant to configure the shortcut options for an a11y feature. 69 * </> 70 * 71 * @param shortcutTargets the a11y features, like color correction, Talkback, etc. 72 * @throws NullPointerException if the {@code shortcutTargets} was {@code null} 73 * @throws IllegalArgumentException if the {@code shortcutTargets} was empty 74 */ setShortcutTargets(Set<String> shortcutTargets)75 public void setShortcutTargets(Set<String> shortcutTargets) { 76 Preconditions.checkCollectionNotEmpty(shortcutTargets, /* valueName= */ "a11y targets"); 77 78 this.mShortcutTargets = shortcutTargets; 79 } 80 setInSetupWizard(boolean isInSetupWizard)81 public void setInSetupWizard(boolean isInSetupWizard) { 82 this.mIsInSetupWizard = isInSetupWizard; 83 } 84 getShortcutTargets()85 protected Set<String> getShortcutTargets() { 86 return mShortcutTargets; 87 } 88 isInSetupWizard()89 protected boolean isInSetupWizard() { 90 return mIsInSetupWizard; 91 } 92 93 @Override onPreferenceChange(@onNull Preference preference, Object newValue)94 public final boolean onPreferenceChange(@NonNull Preference preference, Object newValue) { 95 enableShortcutForTargets((Boolean) newValue); 96 return false; 97 } 98 99 @ShortcutConstants.UserShortcutType getShortcutType()100 protected int getShortcutType() { 101 return ShortcutConstants.UserShortcutType.DEFAULT; 102 } 103 104 /** 105 * Returns true if the shortcut is associated to the targets 106 */ isChecked()107 protected boolean isChecked() { 108 Set<String> targets = ShortcutUtils.getShortcutTargetsFromSettings( 109 mContext, getShortcutType(), UserHandle.myUserId()); 110 111 return !targets.isEmpty() && targets.containsAll(getShortcutTargets()); 112 } 113 114 /** 115 * Enable or disable the shortcut for the given accessibility features. 116 */ enableShortcutForTargets(boolean enable)117 protected void enableShortcutForTargets(boolean enable) { 118 Set<String> shortcutTargets = getShortcutTargets(); 119 @ShortcutConstants.UserShortcutType int shortcutType = getShortcutType(); 120 121 if (Flags.a11yQsShortcut()) { 122 AccessibilityManager a11yManager = mContext.getSystemService( 123 AccessibilityManager.class); 124 if (a11yManager != null) { 125 a11yManager.enableShortcutsForTargets(enable, shortcutType, shortcutTargets, 126 UserHandle.myUserId()); 127 } 128 return; 129 } 130 131 if (enable) { 132 for (String target : shortcutTargets) { 133 ShortcutUtils.optInValueToSettings(mContext, shortcutType, target); 134 } 135 } else { 136 for (String target : shortcutTargets) { 137 ShortcutUtils.optOutValueFromSettings(mContext, shortcutType, target); 138 } 139 } 140 ShortcutUtils.updateInvisibleToggleAccessibilityServiceEnableState( 141 mContext, shortcutTargets, UserHandle.myUserId()); 142 } 143 144 /** 145 * Returns true when the user can associate a shortcut to the targets 146 */ isShortcutAvailable()147 protected abstract boolean isShortcutAvailable(); 148 } 149