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