16ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla/* 26ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * Copyright (C) 2017 The Android Open Source Project 36ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * 46ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * Licensed under the Apache License, Version 2.0 (the "License"); 56ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * you may not use this file except in compliance with the License. 66ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * You may obtain a copy of the License at 76ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * 86ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * http://www.apache.org/licenses/LICENSE-2.0 96ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * 106ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * Unless required by applicable law or agreed to in writing, software 116ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * distributed under the License is distributed on an "AS IS" BASIS, 126ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * See the License for the specific language governing permissions and 146ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * limitations under the License. 156ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla */ 166ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 176ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 186ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslapackage android.provider; 196ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 206ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport android.content.ComponentName; 216ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport android.content.ContentResolver; 226ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport android.text.TextUtils; 236ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 246ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport com.android.internal.util.ArrayUtils; 256ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 26cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Suslaimport java.util.Collection; 276ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport java.util.HashSet; 286ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport java.util.Iterator; 296ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslaimport java.util.function.Function; 306ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 316ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla/** 326ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * Utilities for dealing with {@link String} values in {@link Settings} 336ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * 346ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * @hide 356ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla */ 366ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Suslapublic class SettingsStringUtil { 376ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla private SettingsStringUtil() {} 386ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 396ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static final String DELIMITER = ":"; 406ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 416ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla /** 426ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * A {@link HashSet} of items, that uses a common convention of setting string 436ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla * serialization/deserialization of separating multiple items with {@link #DELIMITER} 446ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla */ 456ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static abstract class ColonDelimitedSet<T> extends HashSet<T> { 466ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 476ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public ColonDelimitedSet(String colonSeparatedItems) { 486ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla for (String cn : 496ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla TextUtils.split(TextUtils.emptyIfNull(colonSeparatedItems), DELIMITER)) { 506ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla add(itemFromString(cn)); 516ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 526ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 536ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 546ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla protected abstract T itemFromString(String s); 556ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla protected String itemToString(T item) { 566ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return String.valueOf(item); 576ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 586ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 596ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla @Override 606ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public String toString() { 616ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla StringBuilder sb = new StringBuilder(); 626ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla Iterator<T> it = iterator(); 636ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla if (it.hasNext()) { 64806456f0978218f96a9bf24b80a281e9c5e68805Phil Weaver sb.append(itemToString(it.next())); 656ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla while (it.hasNext()) { 666ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla sb.append(DELIMITER); 676ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla sb.append(itemToString(it.next())); 686ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 696ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 706ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return sb.toString(); 716ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 726ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 736ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 746ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static class OfStrings extends ColonDelimitedSet<String> { 756ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public OfStrings(String colonSeparatedItems) { 766ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla super(colonSeparatedItems); 776ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 786ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 796ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla @Override 806ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla protected String itemFromString(String s) { 816ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return s; 826ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 836ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 84cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla public static String addAll(String delimitedElements, Collection<String> elements) { 85cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla final ColonDelimitedSet<String> set 86cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla = new ColonDelimitedSet.OfStrings(delimitedElements); 87cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla return set.addAll(elements) ? set.toString() : delimitedElements; 88cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla } 89cf00adebec29d4cdbec5bc0f004b26a09327c236Eugene Susla 906ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static String add(String delimitedElements, String element) { 916ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla final ColonDelimitedSet<String> set 926ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla = new ColonDelimitedSet.OfStrings(delimitedElements); 936ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla if (set.contains(element)) { 946ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return delimitedElements; 956ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 966ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla set.add(element); 976ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return set.toString(); 986ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 996ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1006ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static String remove(String delimitedElements, String element) { 1016ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla final ColonDelimitedSet<String> set 1026ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla = new ColonDelimitedSet.OfStrings(delimitedElements); 1036ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla if (!set.contains(element)) { 1046ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return delimitedElements; 1056ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1066ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla set.remove(element); 1076ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return set.toString(); 1086ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1096ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1106ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static boolean contains(String delimitedElements, String element) { 1116ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla final String[] elements = TextUtils.split(delimitedElements, DELIMITER); 1126ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return ArrayUtils.indexOf(elements, element) != -1; 1136ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1146ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1156ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1166ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1176ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static class ComponentNameSet extends ColonDelimitedSet<ComponentName> { 1186ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public ComponentNameSet(String colonSeparatedPackageNames) { 1196ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla super(colonSeparatedPackageNames); 1206ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1216ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1226ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla @Override 1236ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla protected ComponentName itemFromString(String s) { 1246ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return ComponentName.unflattenFromString(s); 1256ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1266ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1276ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla @Override 1286ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla protected String itemToString(ComponentName item) { 1296ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return item.flattenToString(); 1306ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1316ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1326ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static String add(String delimitedElements, ComponentName element) { 1336ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla final ComponentNameSet set = new ComponentNameSet(delimitedElements); 1346ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla if (set.contains(element)) { 1356ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return delimitedElements; 1366ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1376ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla set.add(element); 1386ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return set.toString(); 1396ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1406ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1416ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static String remove(String delimitedElements, ComponentName element) { 1426ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla final ComponentNameSet set = new ComponentNameSet(delimitedElements); 1436ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla if (!set.contains(element)) { 1446ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return delimitedElements; 1456ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1466ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla set.remove(element); 1476ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return set.toString(); 1486ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1496ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1506ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static boolean contains(String delimitedElements, ComponentName element) { 1516ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return ColonDelimitedSet.OfStrings.contains( 1526ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla delimitedElements, element.flattenToString()); 1536ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1546ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1556ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1566ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public static class SettingStringHelper { 1576ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla private final ContentResolver mContentResolver; 1586ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla private final String mSettingName; 1596ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla private final int mUserId; 1606ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1616ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public SettingStringHelper(ContentResolver contentResolver, String name, int userId) { 1626ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla mContentResolver = contentResolver; 1636ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla mUserId = userId; 1646ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla mSettingName = name; 1656ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1666ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1676ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public String read() { 1686ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return Settings.Secure.getStringForUser( 1696ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla mContentResolver, mSettingName, mUserId); 1706ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1716ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1726ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public boolean write(String value) { 1736ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return Settings.Secure.putStringForUser( 1746ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla mContentResolver, mSettingName, value, mUserId); 1756ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1766ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla 1776ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla public boolean modify(Function<String, String> change) { 1786ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla return write(change.apply(read())); 1796ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1806ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla } 1816ed45d8cd33c297e608aba94fc1f61dace7a7ccaEugene Susla} 182