1 /* 2 * Copyright (C) 2017 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.testutils.shadow; 18 19 import static android.provider.Settings.DEFAULT_OVERRIDEABLE_BY_RESTORE; 20 21 import android.content.ContentResolver; 22 import android.provider.Settings; 23 24 import com.google.common.collect.HashBasedTable; 25 import com.google.common.collect.Table; 26 27 import org.robolectric.annotation.Implementation; 28 import org.robolectric.annotation.Implements; 29 import org.robolectric.shadows.ShadowSettings; 30 31 import java.util.Map; 32 import java.util.WeakHashMap; 33 34 @Implements(Settings.Secure.class) 35 public class ShadowSecureSettings extends ShadowSettings.ShadowSecure { 36 37 private static final Map<ContentResolver, Table<Integer, String, Object>> sUserDataMap = 38 new WeakHashMap<>(); 39 40 @Implementation putStringForUser(ContentResolver resolver, String name, String value, String tag, boolean makeDefault, int userHandle, boolean overrideableByRestore)41 public static boolean putStringForUser(ContentResolver resolver, String name, String value, 42 String tag, boolean makeDefault, int userHandle, boolean overrideableByRestore) { 43 final Table<Integer, String, Object> userTable = getUserTable(resolver); 44 synchronized (userTable) { 45 if (value != null) { 46 userTable.put(userHandle, name, value); 47 } else { 48 userTable.remove(userHandle, name); 49 } 50 return true; 51 } 52 } 53 54 /** 55 * Same implementation as Settings.Secure because robolectric.ShadowSettings.ShadowSecure 56 * overrides this API. 57 */ 58 @Implementation putString(ContentResolver resolver, String name, String value)59 public static boolean putString(ContentResolver resolver, String name, String value) { 60 return putStringForUser(resolver, name, value, null, false, 61 resolver.getUserId(), DEFAULT_OVERRIDEABLE_BY_RESTORE); 62 } 63 64 @Implementation getStringForUser(ContentResolver resolver, String name, int userHandle)65 public static String getStringForUser(ContentResolver resolver, String name, int userHandle) { 66 final Table<Integer, String, Object> userTable = getUserTable(resolver); 67 synchronized (userTable) { 68 return (String) userTable.get(userHandle, name); 69 } 70 } 71 72 /** 73 * Same implementation as Settings.Secure because robolectric.ShadowSettings.ShadowSecure 74 * overrides this API. 75 */ 76 @Implementation putInt(ContentResolver resolver, String name, int value)77 public static boolean putInt(ContentResolver resolver, String name, int value) { 78 return putIntForUser(resolver, name, value, resolver.getUserId()); 79 } 80 81 @Implementation putIntForUser(ContentResolver resolver, String name, int value, int userHandle)82 public static boolean putIntForUser(ContentResolver resolver, String name, int value, 83 int userHandle) { 84 final Table<Integer, String, Object> userTable = getUserTable(resolver); 85 synchronized (userTable) { 86 userTable.put(userHandle, name, value); 87 return true; 88 } 89 } 90 91 /** 92 * Same implementation as Settings.Secure because robolectric.ShadowSettings.ShadowSecure 93 * overrides this API. 94 */ 95 @Implementation getInt(ContentResolver resolver, String name, int def)96 public static int getInt(ContentResolver resolver, String name, int def) { 97 return getIntForUser(resolver, name, def, resolver.getUserId()); 98 } 99 100 @Implementation getIntForUser(ContentResolver resolver, String name, int def, int userHandle)101 public static int getIntForUser(ContentResolver resolver, String name, int def, 102 int userHandle) { 103 final Table<Integer, String, Object> userTable = getUserTable(resolver); 104 synchronized (userTable) { 105 final Object object = userTable.get(userHandle, name); 106 return object instanceof Integer ? (Integer) object : def; 107 } 108 } 109 110 @Implementation putLongForUser(ContentResolver resolver, String name, long value, int userHandle)111 public static boolean putLongForUser(ContentResolver resolver, String name, long value, 112 int userHandle) { 113 final Table<Integer, String, Object> userTable = getUserTable(resolver); 114 synchronized (userTable) { 115 userTable.put(userHandle, name, value); 116 return true; 117 } 118 } 119 120 @Implementation getLongForUser(ContentResolver resolver, String name, long def, int userHandle)121 public static long getLongForUser(ContentResolver resolver, String name, long def, 122 int userHandle) { 123 final Table<Integer, String, Object> userTable = getUserTable(resolver); 124 synchronized (userTable) { 125 final Object object = userTable.get(userHandle, name); 126 return object instanceof Long ? (Long) object : def; 127 } 128 } 129 130 @Implementation putFloatForUser( ContentResolver resolver, String name, float value, int userHandle)131 public static boolean putFloatForUser( 132 ContentResolver resolver, String name, float value, int userHandle) { 133 final Table<Integer, String, Object> userTable = getUserTable(resolver); 134 synchronized (userTable) { 135 userTable.put(userHandle, name, value); 136 return true; 137 } 138 } 139 140 @Implementation getFloatForUser( ContentResolver resolver, String name, float def, int userHandle)141 public static float getFloatForUser( 142 ContentResolver resolver, String name, float def, int userHandle) { 143 final Table<Integer, String, Object> userTable = getUserTable(resolver); 144 synchronized (userTable) { 145 final Object object = userTable.get(userHandle, name); 146 return object instanceof Float ? (Float) object : def; 147 } 148 } 149 clear()150 public static void clear() { 151 synchronized (sUserDataMap) { 152 sUserDataMap.clear(); 153 } 154 } 155 getUserTable(ContentResolver contentResolver)156 private static Table<Integer, String, Object> getUserTable(ContentResolver contentResolver) { 157 synchronized (sUserDataMap) { 158 Table<Integer, String, Object> table = sUserDataMap.get(contentResolver); 159 if (table == null) { 160 table = HashBasedTable.create(); 161 sUserDataMap.put(contentResolver, table); 162 } 163 return table; 164 } 165 } 166 } 167