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 static junit.framework.Assert.assertEquals; 20 import static junit.framework.Assert.assertNull; 21 import static junit.framework.Assert.assertSame; 22 import static junit.framework.Assert.fail; 23 24 import android.content.ContentResolver; 25 import android.content.ContentValues; 26 import android.database.ContentObserver; 27 import android.database.Cursor; 28 import android.net.Uri; 29 import android.os.Handler; 30 import android.os.Looper; 31 import android.os.SystemClock; 32 import android.os.UserHandle; 33 import android.provider.Settings; 34 import android.util.Log; 35 36 import org.junit.Test; 37 38 import java.util.concurrent.atomic.AtomicBoolean; 39 40 /** 41 * Tests for the SettingContentProvider. 42 * 43 * Before you run this test you must add a secondary user. 44 */ 45 public class SettingsProviderTest extends BaseSettingsProviderTest { 46 private static final String LOG_TAG = "SettingsProviderTest"; 47 48 private static final long WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS = 2000; // 2 sec 49 50 private static final String[] NAME_VALUE_COLUMNS = new String[]{ 51 Settings.NameValueTable.NAME, Settings.NameValueTable.VALUE 52 }; 53 54 private final Object mLock = new Object(); 55 56 @Test testSetAndGetGlobalViaFrontEndApiForSystemUser()57 public void testSetAndGetGlobalViaFrontEndApiForSystemUser() throws Exception { 58 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, UserHandle.USER_SYSTEM); 59 } 60 61 @Test testSetAndGetGlobalViaFrontEndApiForNonSystemUser()62 public void testSetAndGetGlobalViaFrontEndApiForNonSystemUser() throws Exception { 63 final int secondaryUserId = getSecondaryUserId(); 64 if (secondaryUserId == UserHandle.USER_SYSTEM) { 65 Log.w(LOG_TAG, "No secondary user. Skipping " 66 + "testSetAndGetGlobalViaFrontEndApiForNonSystemUser"); 67 return; 68 } 69 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_GLOBAL, secondaryUserId); 70 } 71 72 @Test testSetAndGetSecureViaFrontEndApiForSystemUser()73 public void testSetAndGetSecureViaFrontEndApiForSystemUser() throws Exception { 74 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, UserHandle.USER_SYSTEM); 75 } 76 77 @Test testSetAndGetSecureViaFrontEndApiForNonSystemUser()78 public void testSetAndGetSecureViaFrontEndApiForNonSystemUser() throws Exception { 79 final int secondaryUserId = getSecondaryUserId(); 80 if (secondaryUserId == UserHandle.USER_SYSTEM) { 81 Log.w(LOG_TAG, "No secondary user. Skipping " 82 + "testSetAndGetSecureViaFrontEndApiForNonSystemUser"); 83 return; 84 } 85 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SECURE, secondaryUserId); 86 } 87 88 @Test testSetAndGetSystemViaFrontEndApiForSystemUser()89 public void testSetAndGetSystemViaFrontEndApiForSystemUser() throws Exception { 90 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, UserHandle.USER_SYSTEM); 91 } 92 93 @Test testSetAndGetSystemViaFrontEndApiForNonSystemUser()94 public void testSetAndGetSystemViaFrontEndApiForNonSystemUser() throws Exception { 95 final int secondaryUserId = getSecondaryUserId(); 96 if (secondaryUserId == UserHandle.USER_SYSTEM) { 97 Log.w(LOG_TAG, "No secondary user. Skipping " 98 + "testSetAndGetSystemViaFrontEndApiForNonSystemUser"); 99 return; 100 } 101 performSetAndGetSettingTestViaFrontEndApi(SETTING_TYPE_SYSTEM, secondaryUserId); 102 } 103 104 @Test testSetAndGetGlobalViaProviderApi()105 public void testSetAndGetGlobalViaProviderApi() throws Exception { 106 performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_GLOBAL); 107 } 108 109 @Test testSetAndGetSecureViaProviderApi()110 public void testSetAndGetSecureViaProviderApi() throws Exception { 111 performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SECURE); 112 } 113 114 @Test testSetAndGetSystemViaProviderApi()115 public void testSetAndGetSystemViaProviderApi() throws Exception { 116 performSetAndGetSettingTestViaProviderApi(SETTING_TYPE_SYSTEM); 117 } 118 119 @Test testSelectAllGlobalViaProviderApi()120 public void testSelectAllGlobalViaProviderApi() throws Exception { 121 setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_GLOBAL, 122 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 123 try { 124 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_GLOBAL, 125 FAKE_SETTING_NAME); 126 } finally { 127 deleteStringViaProviderApi(SETTING_TYPE_GLOBAL, FAKE_SETTING_NAME); 128 } 129 } 130 131 // TODO(b/142206242): make this less flaky and re-enable it 132 // @Test 133 // public void testSelectAllSecureViaProviderApi() throws Exception { 134 // setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SECURE, 135 // FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 136 // try { 137 // queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SECURE, 138 // FAKE_SETTING_NAME); 139 // } finally { 140 // deleteStringViaProviderApi(SETTING_TYPE_SECURE, FAKE_SETTING_NAME); 141 // } 142 // } 143 144 @Test testSelectAllSystemViaProviderApi()145 public void testSelectAllSystemViaProviderApi() throws Exception { 146 setSettingViaProviderApiAndAssertSuccessfulChange(SETTING_TYPE_SYSTEM, 147 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, true); 148 try { 149 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(SETTING_TYPE_SYSTEM, 150 FAKE_SETTING_NAME); 151 } finally { 152 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 153 } 154 } 155 156 @Test testQueryUpdateDeleteGlobalViaProviderApi()157 public void testQueryUpdateDeleteGlobalViaProviderApi() throws Exception { 158 doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_GLOBAL); 159 } 160 161 @Test testQueryUpdateDeleteSecureViaProviderApi()162 public void testQueryUpdateDeleteSecureViaProviderApi() throws Exception { 163 doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SECURE); 164 } 165 166 @Test testQueryUpdateDeleteSystemViaProviderApi()167 public void testQueryUpdateDeleteSystemViaProviderApi() throws Exception { 168 doTestQueryUpdateDeleteGlobalViaProviderApiForType(SETTING_TYPE_SYSTEM); 169 } 170 171 @Test testBulkInsertGlobalViaProviderApi()172 public void testBulkInsertGlobalViaProviderApi() throws Exception { 173 toTestBulkInsertViaProviderApiForType(SETTING_TYPE_GLOBAL); 174 } 175 176 @Test testBulkInsertSystemViaProviderApi()177 public void testBulkInsertSystemViaProviderApi() throws Exception { 178 toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SYSTEM); 179 } 180 181 @Test testBulkInsertSecureViaProviderApi()182 public void testBulkInsertSecureViaProviderApi() throws Exception { 183 toTestBulkInsertViaProviderApiForType(SETTING_TYPE_SECURE); 184 } 185 186 @Test testAppCannotRunsSystemOutOfMemoryWritingSystemSettings()187 public void testAppCannotRunsSystemOutOfMemoryWritingSystemSettings() throws Exception { 188 int insertedCount = 0; 189 try { 190 for (; insertedCount < 1200; insertedCount++) { 191 insertStringViaProviderApi(SETTING_TYPE_SYSTEM, 192 String.valueOf(insertedCount), FAKE_SETTING_VALUE, false); 193 } 194 fail("Adding app specific settings must be bound."); 195 } catch (Exception e) { 196 // expected 197 } finally { 198 for (; insertedCount >= 0; insertedCount--) { 199 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, 200 String.valueOf(insertedCount)); 201 } 202 } 203 } 204 205 @Test testQueryStringInBracketsGlobalViaProviderApiForType()206 public void testQueryStringInBracketsGlobalViaProviderApiForType() throws Exception { 207 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_GLOBAL); 208 } 209 210 @Test testQueryStringInBracketsSecureViaProviderApiForType()211 public void testQueryStringInBracketsSecureViaProviderApiForType() throws Exception { 212 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SECURE); 213 } 214 215 @Test testQueryStringInBracketsSystemViaProviderApiForType()216 public void testQueryStringInBracketsSystemViaProviderApiForType() throws Exception { 217 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SYSTEM); 218 } 219 220 @Test testQueryStringWithAppendedNameToUriViaProviderApi()221 public void testQueryStringWithAppendedNameToUriViaProviderApi() throws Exception { 222 // Make sure we have a clean slate. 223 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 224 225 try { 226 // Insert the setting. 227 final Uri uri = insertStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME, 228 FAKE_SETTING_VALUE, false); 229 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(SETTING_TYPE_SYSTEM), 230 FAKE_SETTING_NAME); 231 assertEquals("Did not get expected Uri.", expectUri, uri); 232 233 // Make sure the first setting is there. 234 String firstValue = queryStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME, 235 false, true); 236 assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue); 237 } finally { 238 // Clean up. 239 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 240 } 241 } 242 243 @Test testResetModePackageDefaultsGlobal()244 public void testResetModePackageDefaultsGlobal() throws Exception { 245 testResetModePackageDefaultsCommon(SETTING_TYPE_GLOBAL); 246 } 247 248 @Test testResetModePackageDefaultsSecure()249 public void testResetModePackageDefaultsSecure() throws Exception { 250 testResetModePackageDefaultsCommon(SETTING_TYPE_SECURE); 251 } 252 testResetModePackageDefaultsCommon(int type)253 private void testResetModePackageDefaultsCommon(int type) throws Exception { 254 // Make sure we have a clean slate. 255 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 256 try { 257 // Set a value but don't make it the default 258 setSettingViaShell(type, FAKE_SETTING_NAME, 259 FAKE_SETTING_VALUE, false); 260 261 // Reset the changes made by the "shell/root" package 262 resetToDefaultsViaShell(type, "com.android.shell"); 263 resetToDefaultsViaShell(type, "root"); 264 265 // Make sure the old APIs don't set defaults 266 assertNull(getSetting(type, FAKE_SETTING_NAME)); 267 268 // Set a value and make it the default 269 setSettingViaShell(type, FAKE_SETTING_NAME, 270 FAKE_SETTING_VALUE, true); 271 // Change the setting from the default 272 setSettingViaShell(type, FAKE_SETTING_NAME, 273 FAKE_SETTING_VALUE_2, false); 274 275 // Reset the changes made by this package 276 resetToDefaultsViaShell(type, "com.android.shell"); 277 resetToDefaultsViaShell(type, "root"); 278 279 // Make sure the old APIs don't set defaults 280 assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME)); 281 } finally { 282 // Make sure we have a clean slate. 283 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 284 } 285 } 286 287 @Test testResetModePackageDefaultsWithTokensGlobal()288 public void testResetModePackageDefaultsWithTokensGlobal() throws Exception { 289 testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_GLOBAL); 290 } 291 292 @Test testResetModePackageDefaultsWithTokensSecure()293 public void testResetModePackageDefaultsWithTokensSecure() throws Exception { 294 testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_SECURE); 295 } 296 testResetModePackageDefaultsWithTokensCommon(int type)297 private void testResetModePackageDefaultsWithTokensCommon(int type) throws Exception { 298 // Make sure we have a clean slate. 299 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 300 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 301 try { 302 // Set a default value 303 setSettingViaShell(type, FAKE_SETTING_NAME, 304 FAKE_SETTING_VALUE, true); 305 // Change the default and associate a token 306 setSettingViaShell(type, FAKE_SETTING_NAME, 307 FAKE_SETTING_VALUE_2, "TOKEN1", false); 308 309 // Set a default value 310 setSettingViaShell(type, FAKE_SETTING_NAME_1, 311 FAKE_SETTING_VALUE, "TOKEN2", true); 312 // Change the default and associate a token 313 setSettingViaShell(type, FAKE_SETTING_NAME_1, 314 FAKE_SETTING_VALUE_2, "TOKEN2", false); 315 316 // Reset settings associated with TOKEN1 317 resetToDefaultsViaShell(type, "com.android.shell", "TOKEN1"); 318 resetToDefaultsViaShell(type, "root", "TOKEN1"); 319 320 // Make sure TOKEN1 settings are reset 321 assertEquals(FAKE_SETTING_VALUE, getSetting(type, 322 FAKE_SETTING_NAME)); 323 324 // Make sure TOKEN2 settings are not reset 325 assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, 326 FAKE_SETTING_NAME_1)); 327 328 // Reset settings associated with TOKEN2 329 resetToDefaultsViaShell(type, "com.android.shell", "TOKEN2"); 330 resetToDefaultsViaShell(type, "root", "TOKEN2"); 331 332 // Make sure TOKEN2 settings are reset 333 assertEquals(FAKE_SETTING_VALUE, getSetting(type, 334 FAKE_SETTING_NAME_1)); 335 } finally { 336 // Make sure we have a clean slate. 337 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 338 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 339 } 340 } 341 342 @Test testResetModeUntrustedDefaultsGlobal()343 public void testResetModeUntrustedDefaultsGlobal() throws Exception { 344 testResetModeUntrustedDefaultsCommon(SETTING_TYPE_GLOBAL); 345 } 346 347 @Test testResetModeUntrustedDefaultsSecure()348 public void testResetModeUntrustedDefaultsSecure() throws Exception { 349 testResetModeUntrustedDefaultsCommon(SETTING_TYPE_SECURE); 350 } 351 testResetModeUntrustedDefaultsCommon(int type)352 private void testResetModeUntrustedDefaultsCommon(int type) throws Exception { 353 // Make sure we have a clean slate. 354 putSetting(type, FAKE_SETTING_NAME, null); 355 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 356 try { 357 // Set a default setting as a trusted component 358 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE); 359 // Change the setting as a trusted component 360 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2); 361 362 // Set a default setting as an untrusted component 363 setSettingViaShell(type, FAKE_SETTING_NAME_1, 364 FAKE_SETTING_VALUE, true); 365 // Change the setting as an untrusted component 366 setSettingViaShell(type, FAKE_SETTING_NAME_1, 367 FAKE_SETTING_VALUE_2, false); 368 369 // Reset the untrusted changes to defaults 370 resetSettingsViaShell(type, 371 Settings.RESET_MODE_UNTRUSTED_DEFAULTS); 372 373 // Check whether only the untrusted changes set to defaults 374 assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME)); 375 assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME_1)); 376 } finally { 377 // Make sure we have a clean slate. 378 putSetting(type, FAKE_SETTING_NAME, null); 379 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 380 } 381 } 382 383 // TODO(b/142206242): make this less flaky and re-enable it 384 // @Test 385 // public void testResetModeUntrustedClearGlobal() throws Exception { 386 // testResetModeUntrustedClearCommon(SETTING_TYPE_GLOBAL); 387 // } 388 389 @Test testResetModeUntrustedClearSecure()390 public void testResetModeUntrustedClearSecure() throws Exception { 391 testResetModeUntrustedClearCommon(SETTING_TYPE_SECURE); 392 } 393 testResetModeUntrustedClearCommon(int type)394 private void testResetModeUntrustedClearCommon(int type) throws Exception { 395 // Make sure we have a clean slate. 396 putSetting(type, FAKE_SETTING_NAME, null); 397 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 398 try { 399 // Set a default setting as a trusted component 400 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE); 401 // Change the setting as a trusted component 402 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2); 403 404 // Set a default setting as an untrusted component 405 setSettingViaShell(type, FAKE_SETTING_NAME_1, 406 FAKE_SETTING_VALUE, true); 407 // Change the setting as an untrusted component 408 setSettingViaShell(type, FAKE_SETTING_NAME_1, 409 FAKE_SETTING_VALUE_2, false); 410 411 // Clear the untrusted changes 412 resetSettingsViaShell(type, 413 Settings.RESET_MODE_UNTRUSTED_CHANGES); 414 415 // Check whether only the untrusted changes set to defaults 416 assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME)); 417 assertNull(getSetting(type, FAKE_SETTING_NAME_1)); 418 } finally { 419 // Make sure we have a clean slate. 420 putSetting(type, FAKE_SETTING_NAME, null); 421 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 422 } 423 } 424 425 // TODO(b/142206242): make this less flaky and re-enable it 426 // @Test 427 // public void testResetModeTrustedDefaultsGlobal() throws Exception { 428 // testResetModeTrustedDefaultsCommon(SETTING_TYPE_GLOBAL); 429 // } 430 431 @Test testResetModeTrustedDefaultsSecure()432 public void testResetModeTrustedDefaultsSecure() throws Exception { 433 testResetModeTrustedDefaultsCommon(SETTING_TYPE_SECURE); 434 } 435 testResetModeTrustedDefaultsCommon(int type)436 private void testResetModeTrustedDefaultsCommon(int type) throws Exception { 437 // Make sure we have a clean slate. 438 putSetting(type, FAKE_SETTING_NAME, null); 439 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 440 try { 441 // Set a default setting as a trusted component 442 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE); 443 // Change the setting as a trusted component 444 setSettingViaShell(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2, false); 445 446 // Set a default setting as an untrusted component 447 setSettingViaShell(type, FAKE_SETTING_NAME_1, 448 FAKE_SETTING_VALUE, true); 449 // Change the setting as an untrusted component 450 setSettingViaShell(type, FAKE_SETTING_NAME_1, 451 FAKE_SETTING_VALUE_2, false); 452 453 // Reset to trusted defaults 454 resetSettingsViaShell(type, 455 Settings.RESET_MODE_TRUSTED_DEFAULTS); 456 457 // Check whether snapped to trusted defaults 458 assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME)); 459 assertNull(getSetting(type, FAKE_SETTING_NAME_1)); 460 } finally { 461 // Make sure we have a clean slate. 462 putSetting(type, FAKE_SETTING_NAME, null); 463 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 464 } 465 } 466 467 // To prevent FRP bypasses, the SECURE_FRP_MODE setting should not be reset when all other 468 // settings are reset. But it should still be possible to explicitly set its value. 469 @Test testSecureFrpModeSettingCannotBeReset()470 public void testSecureFrpModeSettingCannotBeReset() throws Exception { 471 final String name = Settings.Global.SECURE_FRP_MODE; 472 final String origValue = getSetting(SETTING_TYPE_GLOBAL, name); 473 setSettingViaShell(SETTING_TYPE_GLOBAL, name, "1", false); 474 try { 475 assertEquals("1", getSetting(SETTING_TYPE_GLOBAL, name)); 476 for (int type : new int[] { SETTING_TYPE_GLOBAL, SETTING_TYPE_SECURE }) { 477 resetSettingsViaShell(type, Settings.RESET_MODE_UNTRUSTED_DEFAULTS); 478 resetSettingsViaShell(type, Settings.RESET_MODE_UNTRUSTED_CHANGES); 479 resetSettingsViaShell(type, Settings.RESET_MODE_TRUSTED_DEFAULTS); 480 } 481 // The value should still be "1". It should not have been reset to null. 482 assertEquals("1", getSetting(SETTING_TYPE_GLOBAL, name)); 483 // It should still be possible to explicitly set the value to "0". 484 setSettingViaShell(SETTING_TYPE_GLOBAL, name, "0", false); 485 assertEquals("0", getSetting(SETTING_TYPE_GLOBAL, name)); 486 } finally { 487 setSettingViaShell(SETTING_TYPE_GLOBAL, name, origValue, false); 488 assertEquals(origValue, getSetting(SETTING_TYPE_GLOBAL, name)); 489 } 490 } 491 doTestQueryStringInBracketsViaProviderApiForType(int type)492 private void doTestQueryStringInBracketsViaProviderApiForType(int type) { 493 // Make sure we have a clean slate. 494 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 495 496 try { 497 // Insert the setting. 498 final Uri uri = insertStringViaProviderApi(type, FAKE_SETTING_NAME, 499 FAKE_SETTING_VALUE, false); 500 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME); 501 assertEquals("Did not get expected Uri.", expectUri, uri); 502 503 // Make sure the first setting is there. 504 String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME, true, false); 505 assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue); 506 } finally { 507 // Clean up. 508 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 509 } 510 } 511 toTestBulkInsertViaProviderApiForType(int type)512 private void toTestBulkInsertViaProviderApiForType(int type) { 513 // Make sure we have a clean slate. 514 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 515 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1); 516 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2); 517 518 try { 519 Uri uri = getBaseUriForType(type); 520 ContentValues[] allValues = new ContentValues[3]; 521 522 // Insert the first setting. 523 ContentValues firstValues = new ContentValues(); 524 firstValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME); 525 firstValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE); 526 allValues[0] = firstValues; 527 528 // Insert the second setting. 529 ContentValues secondValues = new ContentValues(); 530 secondValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_1); 531 secondValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_1); 532 allValues[1] = secondValues; 533 534 // Insert the third setting. (null) 535 ContentValues thirdValues = new ContentValues(); 536 thirdValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_2); 537 thirdValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_2); 538 allValues[2] = thirdValues; 539 540 // Verify insertion count. 541 final int insertCount = getContext().getContentResolver().bulkInsert(uri, allValues); 542 assertSame("Couldn't insert both values", 3, insertCount); 543 544 // Make sure the first setting is there. 545 String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 546 assertEquals("First setting must be present", FAKE_SETTING_VALUE, firstValue); 547 548 // Make sure the second setting is there. 549 String secondValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_1); 550 assertEquals("Second setting must be present", FAKE_SETTING_VALUE_1, secondValue); 551 552 // Make sure the third setting is there. 553 String thirdValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_2); 554 assertEquals("Third setting must be present", FAKE_SETTING_VALUE_2, thirdValue); 555 } finally { 556 // Clean up. 557 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 558 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1); 559 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2); 560 } 561 } 562 doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type)563 private void doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type) throws Exception { 564 // Make sure it is not there. 565 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 566 567 // Now selection should return nothing. 568 String value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 569 assertNull("Setting should not be present.", value); 570 571 // Insert the setting. 572 Uri uri = insertStringViaProviderApi(type, 573 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 574 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME); 575 assertEquals("Did not get expected Uri.", expectUri, uri); 576 577 // Now selection should return the setting. 578 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 579 assertEquals("Setting should be present.", FAKE_SETTING_VALUE, value); 580 581 // Update the setting. 582 final int changeCount = updateStringViaProviderApiSetting(type, 583 FAKE_SETTING_NAME, FAKE_SETTING_VALUE_1); 584 assertEquals("Did not get expected change count.", 1, changeCount); 585 586 // Now selection should return the new setting. 587 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 588 assertEquals("Setting should be present.", FAKE_SETTING_VALUE_1, value); 589 590 // Delete the setting. 591 final int deletedCount = deleteStringViaProviderApi(type, 592 FAKE_SETTING_NAME); 593 assertEquals("Did not get expected deleted count", 1, deletedCount); 594 595 // Now selection should return nothing. 596 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 597 assertNull("Setting should not be present.", value); 598 } 599 performSetAndGetSettingTestViaFrontEndApi(int type, int userId)600 private void performSetAndGetSettingTestViaFrontEndApi(int type, int userId) 601 throws Exception { 602 try { 603 // Change the setting and assert a successful change. 604 setSettingViaFrontEndApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, 605 FAKE_SETTING_VALUE, userId); 606 } finally { 607 // Remove the setting. 608 setStringViaFrontEndApiSetting(type, FAKE_SETTING_NAME, null, userId); 609 } 610 } 611 performSetAndGetSettingTestViaProviderApi(int type)612 private void performSetAndGetSettingTestViaProviderApi(int type) 613 throws Exception { 614 try { 615 // Change the setting and assert a successful change. 616 setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, 617 FAKE_SETTING_VALUE, true); 618 } finally { 619 // Remove the setting. 620 setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, null, 621 true); 622 } 623 } 624 setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId)625 private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, 626 final String name, final String value, final int userId) throws Exception { 627 setSettingAndAssertSuccessfulChange(() -> { 628 setStringViaFrontEndApiSetting(type, name, value, userId); 629 }, type, name, value, userId); 630 } 631 setSettingViaProviderApiAndAssertSuccessfulChange(final int type, final String name, final String value, final boolean withTableRowUri)632 private void setSettingViaProviderApiAndAssertSuccessfulChange(final int type, 633 final String name, final String value, final boolean withTableRowUri) 634 throws Exception { 635 setSettingAndAssertSuccessfulChange(() -> { 636 insertStringViaProviderApi(type, name, value, withTableRowUri); 637 }, type, name, value, UserHandle.USER_SYSTEM); 638 } 639 setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, final String name, final String value, final int userId)640 private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, 641 final String name, final String value, final int userId) throws Exception { 642 ContentResolver contentResolver = getContext().getContentResolver(); 643 644 final Uri settingUri = getBaseUriForType(type).buildUpon().appendPath(name).build(); 645 646 final AtomicBoolean success = new AtomicBoolean(); 647 648 ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { 649 public void onChange(boolean selfChange, Uri changeUri, int changeId) { 650 Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")"); 651 assertEquals("Wrong change Uri", changeUri, settingUri); 652 assertEquals("Wrong user id", userId, changeId); 653 String changeValue = getStringViaFrontEndApiSetting(type, name, userId); 654 assertEquals("Wrong setting value", value, changeValue); 655 656 success.set(true); 657 658 synchronized (mLock) { 659 mLock.notifyAll(); 660 } 661 } 662 }; 663 664 contentResolver.registerContentObserver(settingUri, false, contentObserver, userId); 665 666 try { 667 setCommand.run(); 668 669 final long startTimeMillis = SystemClock.uptimeMillis(); 670 synchronized (mLock) { 671 while (true) { 672 if (success.get()) { 673 return; 674 } 675 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 676 if (elapsedTimeMillis >= WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) { 677 fail("Could not change setting for " 678 + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms"); 679 } 680 final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS 681 - elapsedTimeMillis; 682 try { 683 mLock.wait(remainingTimeMillis); 684 } catch (InterruptedException ie) { 685 /* ignore */ 686 } 687 } 688 } 689 } finally { 690 contentResolver.unregisterContentObserver(contentObserver); 691 } 692 } 693 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, String name)694 private void queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, 695 String name) { 696 Uri uri = getBaseUriForType(type); 697 698 Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS, 699 null, null, null); 700 701 if (cursor == null || !cursor.moveToFirst()) { 702 fail("Nothing selected"); 703 } 704 705 try { 706 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME); 707 708 while (cursor.moveToNext()) { 709 String currentName = cursor.getString(nameColumnIdx); 710 if (name.equals(currentName)) { 711 return; 712 } 713 } 714 715 fail("Not found setting: " + name); 716 } finally { 717 cursor.close(); 718 } 719 } 720 } 721