1 /* 2 * Copyright (C) 2020 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; 18 19 import android.content.ComponentName; 20 import android.content.Context; 21 import android.content.SharedPreferences; 22 import android.os.UserHandle; 23 import android.util.ArrayMap; 24 import android.view.accessibility.Flags; 25 26 import androidx.annotation.NonNull; 27 import androidx.annotation.VisibleForTesting; 28 29 import com.android.internal.accessibility.common.ShortcutConstants; 30 import com.android.internal.accessibility.util.ShortcutUtils; 31 import com.android.settings.accessibility.AccessibilityUtil.UserShortcutType; 32 33 import java.util.HashSet; 34 import java.util.Map; 35 import java.util.Set; 36 37 /** Static utility methods relating to {@link PreferredShortcut} */ 38 public final class PreferredShortcuts { 39 40 private static final String ACCESSIBILITY_PERF = "accessibility_prefs"; 41 private static final String USER_SHORTCUT_TYPE = "user_shortcut_type"; 42 43 /** 44 * Retrieves the user preferred shortcut types for the given {@code componentName} from 45 * SharedPreferences. If the user doesn't have a preferred shortcut, 46 * {@link ShortcutConstants.UserShortcutType.SOFTWARE} is returned. 47 * 48 * @param context {@link Context} to access the {@link SharedPreferences} 49 * @param componentName Name of the service or activity, should be the format of {@link 50 * ComponentName#flattenToString()}. 51 * @return {@link ShortcutConstants.UserShortcutType} 52 */ 53 @ShortcutConstants.UserShortcutType retrieveUserShortcutType( @onNull Context context, @NonNull String componentName)54 public static int retrieveUserShortcutType( 55 @NonNull Context context, @NonNull String componentName) { 56 return retrieveUserShortcutType( 57 context, componentName, ShortcutConstants.UserShortcutType.SOFTWARE); 58 } 59 60 /** 61 * Retrieves the user preferred shortcut types for the given {@code componentName} from 62 * SharedPreferences. 63 * 64 * @param context {@link Context} to access the {@link SharedPreferences} 65 * @param componentName Name of the service or activity, should be the format of {@link 66 * ComponentName#flattenToString()}. 67 * @param defaultTypes The default shortcut types to use if the user doesn't have a 68 * preferred shortcut. 69 * @return {@link ShortcutConstants.UserShortcutType} 70 */ 71 @ShortcutConstants.UserShortcutType retrieveUserShortcutType( @onNull Context context, @NonNull String componentName, @ShortcutConstants.UserShortcutType int defaultTypes)72 public static int retrieveUserShortcutType( 73 @NonNull Context context, 74 @NonNull String componentName, 75 @ShortcutConstants.UserShortcutType int defaultTypes) { 76 77 // Create a mutable set to modify 78 final Set<String> info = new HashSet<>(getFromSharedPreferences(context)); 79 info.removeIf(str -> !str.contains(componentName)); 80 81 if (info.isEmpty()) { 82 return defaultTypes; 83 } 84 85 final String str = info.stream().findFirst().get(); 86 final PreferredShortcut shortcut = PreferredShortcut.fromString(str); 87 return shortcut.getType(); 88 } 89 90 /** 91 * Saves a {@link PreferredShortcut} which containing {@link ComponentName#flattenToString()} 92 * and {@link UserShortcutType} in SharedPreferences. 93 * 94 * @param context {@link Context} to access the {@link SharedPreferences} 95 * @param shortcut Contains {@link ComponentName#flattenToString()} and {@link UserShortcutType} 96 */ saveUserShortcutType(Context context, PreferredShortcut shortcut)97 public static void saveUserShortcutType(Context context, PreferredShortcut shortcut) { 98 final String componentName = shortcut.getComponentName(); 99 if (componentName == null) { 100 return; 101 } 102 103 // Create a mutable set to modify 104 final Set<String> info = new HashSet<>(getFromSharedPreferences(context)); 105 info.removeIf(str -> str.contains(componentName)); 106 info.add(shortcut.toString()); 107 saveToSharedPreferences(context, info); 108 } 109 110 /** 111 * Update the user preferred shortcut from Settings data 112 * 113 * @param context {@link Context} to access the {@link SharedPreferences} 114 * @param components contains a set of {@link ComponentName} the service or activity. The 115 * string 116 * representation of the ComponentName should be in the format of 117 * {@link ComponentName#flattenToString()}. 118 */ updatePreferredShortcutsFromSettings( @onNull Context context, @NonNull Set<String> components)119 public static void updatePreferredShortcutsFromSettings( 120 @NonNull Context context, @NonNull Set<String> components) { 121 final Map<Integer, Set<String>> shortcutTypeToTargets = new ArrayMap<>(); 122 for (int shortcutType : ShortcutConstants.USER_SHORTCUT_TYPES) { 123 if (!Flags.a11yQsShortcut() 124 && shortcutType == ShortcutConstants.UserShortcutType.QUICK_SETTINGS) { 125 // Skip saving quick setting as preferred shortcut option when flag is not enabled 126 continue; 127 } 128 shortcutTypeToTargets.put( 129 shortcutType, 130 ShortcutUtils.getShortcutTargetsFromSettings( 131 context, shortcutType, UserHandle.myUserId())); 132 } 133 134 for (String target : components) { 135 int shortcutTypes = ShortcutConstants.UserShortcutType.DEFAULT; 136 for (Map.Entry<Integer, Set<String>> entry : shortcutTypeToTargets.entrySet()) { 137 if (entry.getValue().contains(target)) { 138 shortcutTypes |= entry.getKey(); 139 } 140 } 141 142 if (shortcutTypes != ShortcutConstants.UserShortcutType.DEFAULT) { 143 final PreferredShortcut shortcut = new PreferredShortcut( 144 target, shortcutTypes); 145 PreferredShortcuts.saveUserShortcutType(context, shortcut); 146 } 147 } 148 } 149 150 /** 151 * Returns a immutable set of {@link PreferredShortcut#toString()} list from 152 * SharedPreferences. 153 */ getFromSharedPreferences(Context context)154 private static Set<String> getFromSharedPreferences(Context context) { 155 return getSharedPreferences(context).getStringSet(USER_SHORTCUT_TYPE, Set.of()); 156 } 157 158 /** Sets a set of {@link PreferredShortcut#toString()} list into SharedPreferences. */ saveToSharedPreferences(Context context, Set<String> data)159 private static void saveToSharedPreferences(Context context, Set<String> data) { 160 SharedPreferences.Editor editor = getSharedPreferences(context).edit(); 161 editor.putStringSet(USER_SHORTCUT_TYPE, data).apply(); 162 } 163 getSharedPreferences(Context context)164 private static SharedPreferences getSharedPreferences(Context context) { 165 return context.getSharedPreferences(ACCESSIBILITY_PERF, Context.MODE_PRIVATE); 166 } 167 168 @VisibleForTesting(otherwise = VisibleForTesting.NONE) clearPreferredShortcuts(Context context)169 static void clearPreferredShortcuts(Context context) { 170 getSharedPreferences(context).edit().clear().apply(); 171 } 172 PreferredShortcuts()173 private PreferredShortcuts() {} 174 } 175