SettingsProviderTest.java revision 2849465ee19febd5135cb6ab8cb548a3c8ac6a24
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 17package com.android.providers.settings; 18 19import android.content.ContentResolver; 20import android.content.ContentValues; 21import android.database.ContentObserver; 22import android.database.Cursor; 23import android.net.Uri; 24import android.os.Handler; 25import android.os.Looper; 26import android.os.SystemClock; 27import android.os.UserHandle; 28import android.provider.Settings; 29import android.util.Log; 30 31import java.util.concurrent.atomic.AtomicBoolean; 32 33/** 34 * Tests for the SettingContentProvider. 35 * 36 * Before you run this test you must add a secondary user. 37 */ 38public class SettingsProviderTest extends BaseSettingsProviderTest { 39 private static final String LOG_TAG = "SettingsProviderTest"; 40 41 private static final long WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec 42 43 private static final String[] NAME_VALUE_COLUMNS = new String[]{ 44 Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE 45 }; 46 47 private final Object mLock = new Object(); 48 49 public void testSetAndGetGlobalViaFrontEndApiForOwnerUser() throws Exception { 50 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, UserHandle.USER_OWNER); 51 } 52 53 public void testSetAndGetGlobalViaFrontEndApiForNonOwnerUser() throws Exception { 54 if (mSecondaryUserId == UserHandle.USER_OWNER) { 55 Log.w(LOG_TAG, "No secondary user. Skipping " 56 + "testSetAndGetGlobalViaFrontEndApiForNonOwnerUser"); 57 return; 58 } 59 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, mSecondaryUserId); 60 } 61 62 public void testSetAndGetSecureViaFrontEndApiForOwnerUser() throws Exception { 63 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, UserHandle.USER_OWNER); 64 } 65 66 public void testSetAndGetSecureViaFrontEndApiForNonOwnerUser() throws Exception { 67 if (mSecondaryUserId == UserHandle.USER_OWNER) { 68 Log.w(LOG_TAG, "No secondary user. Skipping " 69 + "testSetAndGetSecureViaFrontEndApiForNonOwnerUser"); 70 return; 71 } 72 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, mSecondaryUserId); 73 } 74 75 public void testSetAndGetSystemViaFrontEndApiForOwnerUser() throws Exception { 76 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, UserHandle.USER_OWNER); 77 } 78 79 public void testSetAndGetSystemViaFrontEndApiForNonOwnerUser() throws Exception { 80 if (mSecondaryUserId == UserHandle.USER_OWNER) { 81 Log.w(LOG_TAG, "No secondary user. Skipping " 82 + "testSetAndGetSystemViaFrontEndApiForNonOwnerUser"); 83 return; 84 } 85 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, mSecondaryUserId); 86 } 87 88 public void testSetAndGetGlobalViaProviderApi() throws Exception { 89 performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_GLOBAL); 90 } 91 92 public void testSetAndGetSecureViaProviderApi() throws Exception { 93 performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SECURE); 94 } 95 96 public void testSetAndGetSystemViaProviderApi() throws Exception { 97 performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SYSTEM); 98 } 99 100 public void testSelectAllGlobalViaProviderApi() throws Exception { 101 setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_GLOBAL, 102 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 103 try { 104 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_GLOBAL, 105 FAKE_SETTING_NAME); 106 } finally { 107 deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME); 108 } 109 } 110 111 public void testSelectAllSecureViaProviderApi() throws Exception { 112 setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SECURE, 113 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 114 try { 115 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SECURE, 116 FAKE_SETTING_NAME); 117 } finally { 118 deleteStringViaProviderApi(SETTING_TYPE_SECURE, FAKE_SETTING_NAME); 119 } 120 } 121 122 public void testSelectAllSystemViaProviderApi() throws Exception { 123 setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SYSTEM, 124 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, true); 125 try { 126 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SYSTEM, 127 FAKE_SETTING_NAME); 128 } finally { 129 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 130 } 131 } 132 133 public void testQueryUpdateDeleteGlobalViaProviderApi() throws Exception { 134 doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_GLOBAL); 135 } 136 137 public void testQueryUpdateDeleteSecureViaProviderApi() throws Exception { 138 doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SECURE); 139 } 140 141 public void testQueryUpdateDeleteSystemViaProviderApi() throws Exception { 142 doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SYSTEM); 143 } 144 145 public void testBulkInsertGlobalViaProviderApi() throws Exception { 146 toTestBulkInsertViaProviderApiForType(SETTING_TYPE_GLOBAL); 147 } 148 149 public void testBulkInsertSystemViaProviderApi() throws Exception { 150 toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SYSTEM); 151 } 152 153 public void testBulkInsertSecureViaProviderApi() throws Exception { 154 toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SECURE); 155 } 156 157 public void testAppCannotRunsSystemOutOfMemoryWritingSystemSettings() throws Exception { 158 int insertedCount = 0; 159 try { 160 for (; insertedCount < 1200; insertedCount++) { 161 Log.w(LOG_TAG, "Adding app specific setting: " + insertedCount); 162 insertStringViaProviderApi(SETTING_TYPE_SYSTEM, 163 String.valueOf(insertedCount), FAKE_SETTING_VALUE, false); 164 } 165 fail("Adding app specific settings must be bound."); 166 } catch (Exception e) { 167 for (; insertedCount >= 0; insertedCount--) { 168 Log.w(LOG_TAG, "Removing app specific setting: " + insertedCount); 169 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, 170 String.valueOf(insertedCount)); 171 } 172 } 173 } 174 175 public void testQueryStringInBracketsGlobalViaProviderApiForType() throws Exception { 176 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_GLOBAL); 177 } 178 179 public void testQueryStringInBracketsSecureViaProviderApiForType() throws Exception { 180 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SECURE); 181 } 182 183 public void testQueryStringInBracketsSystemViaProviderApiForType() throws Exception { 184 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SYSTEM); 185 } 186 187 public void testQueryStringWithAppendedNameToUriViaProviderApi() throws Exception { 188 // Make sure we have a clean slate. 189 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 190 191 try { 192 // Insert the setting. 193 final Uri uri = insertStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME, 194 FAKE_SETTING_VALUE, false); 195 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(SETTING_TYPE_SYSTEM), 196 FAKE_SETTING_NAME); 197 assertEquals("Did not get expected Uri.", expectUri, uri); 198 199 // Make sure the first setting is there. 200 String firstValue = queryStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME, 201 false, true); 202 assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue); 203 } finally { 204 // Clean up. 205 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 206 } 207 } 208 209 private void doTestQueryStringInBracketsViaProviderApiForType(int type) { 210 // Make sure we have a clean slate. 211 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 212 213 try { 214 // Insert the setting. 215 final Uri uri = insertStringViaProviderApi(type, FAKE_SETTING_NAME, 216 FAKE_SETTING_VALUE, false); 217 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME); 218 assertEquals("Did not get expected Uri.", expectUri, uri); 219 220 // Make sure the first setting is there. 221 String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME, true, false); 222 assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue); 223 } finally { 224 // Clean up. 225 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 226 } 227 } 228 229 private void toTestBulkInsertViaProviderApiForType(int type) { 230 // Make sure we have a clean slate. 231 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 232 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1); 233 234 try { 235 Uri uri = getBaseUriForType(type); 236 ContentValues[] allValues = new ContentValues[2]; 237 238 // Insert the first setting. 239 ContentValues firstValues = new ContentValues(); 240 firstValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME); 241 firstValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE); 242 allValues[0] = firstValues; 243 244 // Insert the first setting. 245 ContentValues secondValues = new ContentValues(); 246 secondValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_1); 247 secondValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_1); 248 allValues[1] = secondValues; 249 250 // Verify insertion count. 251 final int insertCount = getContext().getContentResolver().bulkInsert(uri, allValues); 252 assertSame("Couldn't insert both values", 2, insertCount); 253 254 // Make sure the first setting is there. 255 String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 256 assertEquals("First setting must be present", FAKE_SETTING_VALUE, firstValue); 257 258 // Make sure the second setting is there. 259 String secondValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_1); 260 assertEquals("Second setting must be present", FAKE_SETTING_VALUE_1, secondValue); 261 } finally { 262 // Clean up. 263 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 264 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1); 265 } 266 } 267 268 private void doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type) throws Exception { 269 // Make sure it is not there. 270 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 271 272 // Now selection should return nothing. 273 String value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 274 assertNull("Setting should not be present.", value); 275 276 // Insert the setting. 277 Uri uri = insertStringViaProviderApi(type, 278 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 279 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME); 280 assertEquals("Did not get expected Uri.", expectUri, uri); 281 282 // Now selection should return the setting. 283 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 284 assertEquals("Setting should be present.", FAKE_SETTING_VALUE, value); 285 286 // Update the setting. 287 final int changeCount = updateStringViaProviderApiSetting(type, 288 FAKE_SETTING_NAME, FAKE_SETTING_VALUE_1); 289 assertEquals("Did not get expected change count.", 1, changeCount); 290 291 // Now selection should return the new setting. 292 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 293 assertEquals("Setting should be present.", FAKE_SETTING_VALUE_1, value); 294 295 // Delete the setting. 296 final int deletedCount = deleteStringViaProviderApi(type, 297 FAKE_SETTING_NAME); 298 assertEquals("Did not get expected deleted count", 1, deletedCount); 299 300 // Now selection should return nothing. 301 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 302 assertNull("Setting should not be present.", value); 303 } 304 305 private void performSetAndGetSettingTestViaFrontEndApi(int type, int userId) 306 throws Exception { 307 try { 308 // Change the setting and assert a successful change. 309 setSettingViaFrontEndApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, 310 FAKE_SETTING_VALUE, userId); 311 } finally { 312 // Remove the setting. 313 setStringViaFrontEndApiSetting(type, FAKE_SETTING_NAME, null, userId); 314 } 315 } 316 317 private void performSetAndGetSettingTestViaProviderApi(int type) 318 throws Exception { 319 try { 320 // Change the setting and assert a successful change. 321 setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, 322 FAKE_SETTING_VALUE, true); 323 } finally { 324 // Remove the setting. 325 setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, null, 326 true); 327 } 328 } 329 330 private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, 331 final String name, final String value, final int userId) throws Exception { 332 setSettingAndAssertSuccessfulChange(new Runnable() { 333 @Override 334 public void run() { 335 setStringViaFrontEndApiSetting(type, name, value, userId); 336 } 337 }, type, name, value, userId); 338 } 339 340 private void setSettingViaProviderApiAndAssertSuccessfulChange(final int type, 341 final String name, final String value, final boolean withTableRowUri) 342 throws Exception { 343 setSettingAndAssertSuccessfulChange(new Runnable() { 344 @Override 345 public void run() { 346 insertStringViaProviderApi(type, name, value, withTableRowUri); 347 } 348 }, type, name, value, UserHandle.USER_OWNER); 349 } 350 351 private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, 352 final String name, final String value, final int userId) throws Exception { 353 ContentResolver contentResolver = getContext().getContentResolver(); 354 355 final Uri settingUri = getBaseUriForType(type); 356 357 final AtomicBoolean success = new AtomicBoolean(); 358 359 ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { 360 public void onChange(boolean selfChange, Uri changeUri, int changeId) { 361 Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")"); 362 assertEquals("Wrong change Uri", changeUri, settingUri); 363 assertEquals("Wrong user id", userId, changeId); 364 String changeValue = getStringViaFrontEndApiSetting(type, name, userId); 365 assertEquals("Wrong setting value", value, changeValue); 366 367 success.set(true); 368 369 synchronized (mLock) { 370 mLock.notifyAll(); 371 } 372 } 373 }; 374 375 contentResolver.registerContentObserver(settingUri, false, contentObserver, userId); 376 377 try { 378 setCommand.run(); 379 380 final long startTimeMillis = SystemClock.uptimeMillis(); 381 synchronized (mLock) { 382 if (success.get()) { 383 return; 384 } 385 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 386 if (elapsedTimeMillis > WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) { 387 fail("Could not change setting for " 388 + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms"); 389 } 390 final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS 391 - elapsedTimeMillis; 392 try { 393 mLock.wait(remainingTimeMillis); 394 } catch (InterruptedException ie) { 395 /* ignore */ 396 } 397 } 398 } finally { 399 contentResolver.unregisterContentObserver(contentObserver); 400 } 401 } 402 403 private void queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, 404 String name) { 405 Uri uri = getBaseUriForType(type); 406 407 Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS, 408 null, null, null); 409 410 if (cursor == null || !cursor.moveToFirst()) { 411 fail("Nothing selected"); 412 } 413 414 try { 415 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME); 416 417 while (cursor.moveToNext()) { 418 String currentName = cursor.getString(nameColumnIdx); 419 if (name.equals(currentName)) { 420 return; 421 } 422 } 423 424 fail("Not found setting: " + name); 425 } finally { 426 cursor.close(); 427 } 428 } 429} 430