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