1 /* 2 * Copyright (C) 2015 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.providers.settings; 18 19 import android.content.ContentResolver; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.content.pm.UserInfo; 23 import android.database.Cursor; 24 import android.net.Uri; 25 import android.os.UserHandle; 26 import android.os.UserManager; 27 import android.provider.Settings; 28 import android.support.test.InstrumentationRegistry; 29 import android.support.test.runner.AndroidJUnit4; 30 import libcore.io.Streams; 31 import org.junit.runner.RunWith; 32 33 import java.io.FileInputStream; 34 import java.io.IOException; 35 import java.io.InputStream; 36 import java.util.List; 37 38 /** 39 * Base class for the SettingContentProvider tests. 40 */ 41 @RunWith(AndroidJUnit4.class) 42 abstract class BaseSettingsProviderTest { 43 protected static final int SETTING_TYPE_GLOBAL = 1; 44 protected static final int SETTING_TYPE_SECURE = 2; 45 protected static final int SETTING_TYPE_SYSTEM = 3; 46 47 protected static final String FAKE_SETTING_NAME = "fake_setting_name"; 48 protected static final String FAKE_SETTING_NAME_1 = "fake_setting_name1"; 49 protected static final String FAKE_SETTING_NAME_2 = "fake_setting_name2"; 50 protected static final String FAKE_SETTING_VALUE = "fake_setting_value"; 51 protected static final String FAKE_SETTING_VALUE_1 = SettingsStateTest.CRAZY_STRING; 52 protected static final String FAKE_SETTING_VALUE_2 = null; 53 54 private static final String[] NAME_VALUE_COLUMNS = new String[] { 55 Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE 56 }; 57 58 private int mSecondaryUserId = Integer.MIN_VALUE; 59 setStringViaFrontEndApiSetting(int type, String name, String value, int userId)60 protected void setStringViaFrontEndApiSetting(int type, String name, String value, int userId) { 61 ContentResolver contentResolver = getContext().getContentResolver(); 62 63 switch (type) { 64 case SETTING_TYPE_GLOBAL: { 65 Settings.Global.putStringForUser(contentResolver, name, value, userId); 66 } break; 67 68 case SETTING_TYPE_SECURE: { 69 Settings.Secure.putStringForUser(contentResolver, name, value, userId); 70 } break; 71 72 case SETTING_TYPE_SYSTEM: { 73 Settings.System.putStringForUser(contentResolver, name, value, userId); 74 } break; 75 76 default: { 77 throw new IllegalArgumentException("Invalid type: " + type); 78 } 79 } 80 } 81 getStringViaFrontEndApiSetting(int type, String name, int userId)82 protected String getStringViaFrontEndApiSetting(int type, String name, int userId) { 83 ContentResolver contentResolver = getContext().getContentResolver(); 84 85 switch (type) { 86 case SETTING_TYPE_GLOBAL: { 87 return Settings.Global.getStringForUser(contentResolver, name, userId); 88 } 89 90 case SETTING_TYPE_SECURE: { 91 return Settings.Secure.getStringForUser(contentResolver, name, userId); 92 } 93 94 case SETTING_TYPE_SYSTEM: { 95 return Settings.System.getStringForUser(contentResolver, name, userId); 96 } 97 98 default: { 99 throw new IllegalArgumentException("Invalid type: " + type); 100 } 101 } 102 } 103 insertStringViaProviderApi(int type, String name, String value, boolean withTableRowUri)104 protected Uri insertStringViaProviderApi(int type, String name, String value, 105 boolean withTableRowUri) { 106 Uri uri = getBaseUriForType(type); 107 if (withTableRowUri) { 108 uri = Uri.withAppendedPath(uri, name); 109 } 110 ContentValues values = new ContentValues(); 111 values.put(Settings.NameValueTable.NAME, name); 112 values.put(Settings.NameValueTable.VALUE, value); 113 114 return getContext().getContentResolver().insert(uri, values); 115 } 116 deleteStringViaProviderApi(int type, String name)117 protected int deleteStringViaProviderApi(int type, String name) { 118 Uri uri = getBaseUriForType(type); 119 return getContext().getContentResolver().delete(uri, "name=?", new String[]{name}); 120 } 121 updateStringViaProviderApiSetting(int type, String name, String value)122 protected int updateStringViaProviderApiSetting(int type, String name, String value) { 123 Uri uri = getBaseUriForType(type); 124 ContentValues values = new ContentValues(); 125 values.put(Settings.NameValueTable.NAME, name); 126 values.put(Settings.NameValueTable.VALUE, value); 127 return getContext().getContentResolver().update(uri, values, "name=?", 128 new String[]{name}); 129 } 130 queryStringViaProviderApi(int type, String name)131 protected String queryStringViaProviderApi(int type, String name) { 132 return queryStringViaProviderApi(type, name, false, false); 133 } 134 queryStringViaProviderApi(int type, String name, boolean queryStringInQuotes, boolean appendNameToUri)135 protected String queryStringViaProviderApi(int type, String name, boolean queryStringInQuotes, 136 boolean appendNameToUri) { 137 final Uri uri; 138 final String queryString; 139 final String[] queryArgs; 140 141 if (appendNameToUri) { 142 uri = Uri.withAppendedPath(getBaseUriForType(type), name); 143 queryString = null; 144 queryArgs = null; 145 } else { 146 uri = getBaseUriForType(type); 147 queryString = queryStringInQuotes ? "(name=?)" : "name=?"; 148 queryArgs = new String[]{name}; 149 } 150 151 Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS, 152 queryString, queryArgs, null); 153 154 if (cursor == null) { 155 return null; 156 } 157 158 try { 159 if (cursor.moveToFirst()) { 160 final int valueColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.VALUE); 161 return cursor.getString(valueColumnIdx); 162 } 163 } finally { 164 cursor.close(); 165 } 166 167 return null; 168 } 169 resetSettingsViaShell(int type, int resetMode)170 protected static void resetSettingsViaShell(int type, int resetMode) throws IOException { 171 final String modeString; 172 switch (resetMode) { 173 case Settings.RESET_MODE_UNTRUSTED_DEFAULTS: { 174 modeString = "untrusted_defaults"; 175 } break; 176 177 case Settings.RESET_MODE_UNTRUSTED_CHANGES: { 178 modeString = "untrusted_clear"; 179 } break; 180 181 case Settings.RESET_MODE_TRUSTED_DEFAULTS: { 182 modeString = "trusted_defaults"; 183 } break; 184 185 default: { 186 throw new IllegalArgumentException("Invalid reset mode: " + resetMode); 187 } 188 } 189 190 switch (type) { 191 case SETTING_TYPE_GLOBAL: { 192 executeShellCommand("settings reset global " + modeString); 193 } break; 194 195 case SETTING_TYPE_SECURE: { 196 executeShellCommand("settings reset secure " + modeString); 197 } break; 198 199 default: { 200 throw new IllegalArgumentException("Invalid type: " + type); 201 } 202 } 203 } 204 resetToDefaultsViaShell(int type, String packageName)205 protected static void resetToDefaultsViaShell(int type, String packageName) throws IOException { 206 resetToDefaultsViaShell(type, packageName, null); 207 } 208 resetToDefaultsViaShell(int type, String packageName, String tag)209 protected static void resetToDefaultsViaShell(int type, String packageName, String tag) 210 throws IOException { 211 switch (type) { 212 case SETTING_TYPE_GLOBAL: { 213 executeShellCommand("settings reset global " + packageName + " " 214 + (tag != null ? tag : "")); 215 } break; 216 217 case SETTING_TYPE_SECURE: { 218 executeShellCommand("settings reset secure " + packageName + " " 219 + (tag != null ? tag : "")); 220 } break; 221 222 case SETTING_TYPE_SYSTEM: { 223 executeShellCommand("settings reset system " + packageName + " " 224 + (tag != null ? tag : "")); 225 } break; 226 227 default: { 228 throw new IllegalArgumentException("Invalid type: " + type); 229 } 230 } 231 } 232 getSetting(int type, String name)233 protected String getSetting(int type, String name) { 234 switch (type) { 235 case SETTING_TYPE_GLOBAL: { 236 return Settings.Global.getString(getContext().getContentResolver(), name); 237 } 238 239 case SETTING_TYPE_SECURE: { 240 return Settings.Secure.getString(getContext().getContentResolver(), name); 241 } 242 243 case SETTING_TYPE_SYSTEM: { 244 return Settings.System.getString(getContext().getContentResolver(), name); 245 } 246 247 default: { 248 throw new IllegalArgumentException("Invalid type: " + type); 249 } 250 } 251 } 252 putSetting(int type, String name, String value)253 protected void putSetting(int type, String name, String value) { 254 switch (type) { 255 case SETTING_TYPE_GLOBAL: { 256 Settings.Global.putString(getContext().getContentResolver(), name, value); 257 } break; 258 259 case SETTING_TYPE_SECURE: { 260 Settings.Secure.putString(getContext().getContentResolver(), name, value); 261 } break; 262 263 case SETTING_TYPE_SYSTEM: { 264 Settings.System.putString(getContext().getContentResolver(), name, value); 265 } break; 266 267 default: { 268 throw new IllegalArgumentException("Invalid type: " + type); 269 } 270 } 271 } 272 setSettingViaShell(int type, String name, String value, boolean makeDefault)273 protected static void setSettingViaShell(int type, String name, String value, 274 boolean makeDefault) throws IOException { 275 setSettingViaShell(type, name, value, null, makeDefault); 276 } 277 setSettingViaShell(int type, String name, String value, String token, boolean makeDefault)278 protected static void setSettingViaShell(int type, String name, String value, 279 String token, boolean makeDefault) throws IOException { 280 switch (type) { 281 case SETTING_TYPE_GLOBAL: { 282 executeShellCommand("settings put global " + name + " " 283 + value + (token != null ? " " + token : "") 284 + (makeDefault ? " default" : "")); 285 286 } break; 287 288 case SETTING_TYPE_SECURE: { 289 executeShellCommand("settings put secure " + name + " " 290 + value + (token != null ? " " + token : "") 291 + (makeDefault ? " default" : "")); 292 } break; 293 294 case SETTING_TYPE_SYSTEM: { 295 executeShellCommand("settings put system " + name + " " 296 + value + (token != null ? " " + token : "") 297 + (makeDefault ? " default" : "")); 298 } break; 299 300 default: { 301 throw new IllegalArgumentException("Invalid type: " + type); 302 } 303 } 304 } 305 getContext()306 protected Context getContext() { 307 return InstrumentationRegistry.getContext(); 308 } 309 getSecondaryUserId()310 protected int getSecondaryUserId() { 311 if (mSecondaryUserId == Integer.MIN_VALUE) { 312 UserManager userManager = (UserManager) getContext() 313 .getSystemService(Context.USER_SERVICE); 314 List<UserInfo> users = userManager.getUsers(); 315 final int userCount = users.size(); 316 for (int i = 0; i < userCount; i++) { 317 UserInfo user = users.get(i); 318 if (!user.isPrimary() && !user.isManagedProfile()) { 319 mSecondaryUserId = user.id; 320 return mSecondaryUserId; 321 } 322 } 323 } 324 if (mSecondaryUserId == Integer.MIN_VALUE) { 325 mSecondaryUserId = UserHandle.USER_SYSTEM; 326 } 327 return mSecondaryUserId; 328 } 329 getBaseUriForType(int type)330 protected static Uri getBaseUriForType(int type) { 331 switch (type) { 332 case SETTING_TYPE_GLOBAL: { 333 return Settings.Global.CONTENT_URI; 334 } 335 336 case SETTING_TYPE_SECURE: { 337 return Settings.Secure.CONTENT_URI; 338 } 339 340 case SETTING_TYPE_SYSTEM: { 341 return Settings.System.CONTENT_URI; 342 } 343 344 default: { 345 throw new IllegalArgumentException("Invalid type: " + type); 346 } 347 } 348 } 349 executeShellCommand(String command)350 protected static void executeShellCommand(String command) throws IOException { 351 InputStream is = new FileInputStream(InstrumentationRegistry.getInstrumentation() 352 .getUiAutomation().executeShellCommand(command).getFileDescriptor()); 353 Streams.readFully(is); 354 } 355 } 356