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 Log.w(LOG_TAG, "Adding app specific setting: " + insertedCount); 192 insertStringViaProviderApi(SETTING_TYPE_SYSTEM, 193 String.valueOf(insertedCount), FAKE_SETTING_VALUE, false); 194 } 195 fail("Adding app specific settings must be bound."); 196 } catch (Exception e) { 197 // expected 198 } finally { 199 for (; insertedCount >= 0; insertedCount--) { 200 Log.w(LOG_TAG, "Removing app specific setting: " + insertedCount); 201 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, 202 String.valueOf(insertedCount)); 203 } 204 } 205 } 206 207 @Test testQueryStringInBracketsGlobalViaProviderApiForType()208 public void testQueryStringInBracketsGlobalViaProviderApiForType() throws Exception { 209 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_GLOBAL); 210 } 211 212 @Test testQueryStringInBracketsSecureViaProviderApiForType()213 public void testQueryStringInBracketsSecureViaProviderApiForType() throws Exception { 214 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SECURE); 215 } 216 217 @Test testQueryStringInBracketsSystemViaProviderApiForType()218 public void testQueryStringInBracketsSystemViaProviderApiForType() throws Exception { 219 doTestQueryStringInBracketsViaProviderApiForType(SETTING_TYPE_SYSTEM); 220 } 221 222 @Test testQueryStringWithAppendedNameToUriViaProviderApi()223 public void testQueryStringWithAppendedNameToUriViaProviderApi() throws Exception { 224 // Make sure we have a clean slate. 225 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 226 227 try { 228 // Insert the setting. 229 final Uri uri = insertStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME, 230 FAKE_SETTING_VALUE, false); 231 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(SETTING_TYPE_SYSTEM), 232 FAKE_SETTING_NAME); 233 assertEquals("Did not get expected Uri.", expectUri, uri); 234 235 // Make sure the first setting is there. 236 String firstValue = queryStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME, 237 false, true); 238 assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue); 239 } finally { 240 // Clean up. 241 deleteStringViaProviderApi(SETTING_TYPE_SYSTEM, FAKE_SETTING_NAME); 242 } 243 } 244 245 @Test testResetModePackageDefaultsGlobal()246 public void testResetModePackageDefaultsGlobal() throws Exception { 247 testResetModePackageDefaultsCommon(SETTING_TYPE_GLOBAL); 248 } 249 250 @Test testResetModePackageDefaultsSecure()251 public void testResetModePackageDefaultsSecure() throws Exception { 252 testResetModePackageDefaultsCommon(SETTING_TYPE_SECURE); 253 } 254 testResetModePackageDefaultsCommon(int type)255 private void testResetModePackageDefaultsCommon(int type) throws Exception { 256 // Make sure we have a clean slate. 257 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 258 try { 259 // Set a value but don't make it the default 260 setSettingViaShell(type, FAKE_SETTING_NAME, 261 FAKE_SETTING_VALUE, false); 262 263 // Reset the changes made by the "shell/root" package 264 resetToDefaultsViaShell(type, "com.android.shell"); 265 resetToDefaultsViaShell(type, "root"); 266 267 // Make sure the old APIs don't set defaults 268 assertNull(getSetting(type, FAKE_SETTING_NAME)); 269 270 // Set a value and make it the default 271 setSettingViaShell(type, FAKE_SETTING_NAME, 272 FAKE_SETTING_VALUE, true); 273 // Change the setting from the default 274 setSettingViaShell(type, FAKE_SETTING_NAME, 275 FAKE_SETTING_VALUE_2, false); 276 277 // Reset the changes made by this package 278 resetToDefaultsViaShell(type, "com.android.shell"); 279 resetToDefaultsViaShell(type, "root"); 280 281 // Make sure the old APIs don't set defaults 282 assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME)); 283 } finally { 284 // Make sure we have a clean slate. 285 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 286 } 287 } 288 289 @Test testResetModePackageDefaultsWithTokensGlobal()290 public void testResetModePackageDefaultsWithTokensGlobal() throws Exception { 291 testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_GLOBAL); 292 } 293 294 @Test testResetModePackageDefaultsWithTokensSecure()295 public void testResetModePackageDefaultsWithTokensSecure() throws Exception { 296 testResetModePackageDefaultsWithTokensCommon(SETTING_TYPE_SECURE); 297 } 298 testResetModePackageDefaultsWithTokensCommon(int type)299 private void testResetModePackageDefaultsWithTokensCommon(int type) throws Exception { 300 // Make sure we have a clean slate. 301 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 302 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 303 try { 304 // Set a default value 305 setSettingViaShell(type, FAKE_SETTING_NAME, 306 FAKE_SETTING_VALUE, true); 307 // Change the default and associate a token 308 setSettingViaShell(type, FAKE_SETTING_NAME, 309 FAKE_SETTING_VALUE_2, "TOKEN1", false); 310 311 // Set a default value 312 setSettingViaShell(type, FAKE_SETTING_NAME_1, 313 FAKE_SETTING_VALUE, "TOKEN2", true); 314 // Change the default and associate a token 315 setSettingViaShell(type, FAKE_SETTING_NAME_1, 316 FAKE_SETTING_VALUE_2, "TOKEN2", false); 317 318 // Reset settings associated with TOKEN1 319 resetToDefaultsViaShell(type, "com.android.shell", "TOKEN1"); 320 resetToDefaultsViaShell(type, "root", "TOKEN1"); 321 322 // Make sure TOKEN1 settings are reset 323 assertEquals(FAKE_SETTING_VALUE, getSetting(type, 324 FAKE_SETTING_NAME)); 325 326 // Make sure TOKEN2 settings are not reset 327 assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, 328 FAKE_SETTING_NAME_1)); 329 330 // Reset settings associated with TOKEN2 331 resetToDefaultsViaShell(type, "com.android.shell", "TOKEN2"); 332 resetToDefaultsViaShell(type, "root", "TOKEN2"); 333 334 // Make sure TOKEN2 settings are reset 335 assertEquals(FAKE_SETTING_VALUE, getSetting(type, 336 FAKE_SETTING_NAME_1)); 337 } finally { 338 // Make sure we have a clean slate. 339 setSettingViaShell(type, FAKE_SETTING_NAME, null, true); 340 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 341 } 342 } 343 344 @Test testResetModeUntrustedDefaultsGlobal()345 public void testResetModeUntrustedDefaultsGlobal() throws Exception { 346 testResetModeUntrustedDefaultsCommon(SETTING_TYPE_GLOBAL); 347 } 348 349 @Test testResetModeUntrustedDefaultsSecure()350 public void testResetModeUntrustedDefaultsSecure() throws Exception { 351 testResetModeUntrustedDefaultsCommon(SETTING_TYPE_SECURE); 352 } 353 testResetModeUntrustedDefaultsCommon(int type)354 private void testResetModeUntrustedDefaultsCommon(int type) throws Exception { 355 // Make sure we have a clean slate. 356 putSetting(type, FAKE_SETTING_NAME, null); 357 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 358 try { 359 // Set a default setting as a trusted component 360 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE); 361 // Change the setting as a trusted component 362 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2); 363 364 // Set a default setting as an untrusted component 365 setSettingViaShell(type, FAKE_SETTING_NAME_1, 366 FAKE_SETTING_VALUE, true); 367 // Change the setting as an untrusted component 368 setSettingViaShell(type, FAKE_SETTING_NAME_1, 369 FAKE_SETTING_VALUE_2, false); 370 371 // Reset the untrusted changes to defaults 372 resetSettingsViaShell(type, 373 Settings.RESET_MODE_UNTRUSTED_DEFAULTS); 374 375 // Check whether only the untrusted changes set to defaults 376 assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME)); 377 assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME_1)); 378 } finally { 379 // Make sure we have a clean slate. 380 putSetting(type, FAKE_SETTING_NAME, null); 381 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 382 } 383 } 384 385 // TODO(b/142206242): make this less flaky and re-enable it 386 // @Test 387 // public void testResetModeUntrustedClearGlobal() throws Exception { 388 // testResetModeUntrustedClearCommon(SETTING_TYPE_GLOBAL); 389 // } 390 391 @Test testResetModeUntrustedClearSecure()392 public void testResetModeUntrustedClearSecure() throws Exception { 393 testResetModeUntrustedClearCommon(SETTING_TYPE_SECURE); 394 } 395 testResetModeUntrustedClearCommon(int type)396 private void testResetModeUntrustedClearCommon(int type) throws Exception { 397 // Make sure we have a clean slate. 398 putSetting(type, FAKE_SETTING_NAME, null); 399 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 400 try { 401 // Set a default setting as a trusted component 402 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE); 403 // Change the setting as a trusted component 404 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2); 405 406 // Set a default setting as an untrusted component 407 setSettingViaShell(type, FAKE_SETTING_NAME_1, 408 FAKE_SETTING_VALUE, true); 409 // Change the setting as an untrusted component 410 setSettingViaShell(type, FAKE_SETTING_NAME_1, 411 FAKE_SETTING_VALUE_2, false); 412 413 // Clear the untrusted changes 414 resetSettingsViaShell(type, 415 Settings.RESET_MODE_UNTRUSTED_CHANGES); 416 417 // Check whether only the untrusted changes set to defaults 418 assertEquals(FAKE_SETTING_VALUE_2, getSetting(type, FAKE_SETTING_NAME)); 419 assertNull(getSetting(type, FAKE_SETTING_NAME_1)); 420 } finally { 421 // Make sure we have a clean slate. 422 putSetting(type, FAKE_SETTING_NAME, null); 423 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 424 } 425 } 426 427 // TODO(b/142206242): make this less flaky and re-enable it 428 // @Test 429 // public void testResetModeTrustedDefaultsGlobal() throws Exception { 430 // testResetModeTrustedDefaultsCommon(SETTING_TYPE_GLOBAL); 431 // } 432 433 @Test testResetModeTrustedDefaultsSecure()434 public void testResetModeTrustedDefaultsSecure() throws Exception { 435 testResetModeTrustedDefaultsCommon(SETTING_TYPE_SECURE); 436 } 437 testResetModeTrustedDefaultsCommon(int type)438 private void testResetModeTrustedDefaultsCommon(int type) throws Exception { 439 // Make sure we have a clean slate. 440 putSetting(type, FAKE_SETTING_NAME, null); 441 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 442 try { 443 // Set a default setting as a trusted component 444 putSetting(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE); 445 // Change the setting as a trusted component 446 setSettingViaShell(type, FAKE_SETTING_NAME, FAKE_SETTING_VALUE_2, false); 447 448 // Set a default setting as an untrusted component 449 setSettingViaShell(type, FAKE_SETTING_NAME_1, 450 FAKE_SETTING_VALUE, true); 451 // Change the setting as an untrusted component 452 setSettingViaShell(type, FAKE_SETTING_NAME_1, 453 FAKE_SETTING_VALUE_2, false); 454 455 // Reset to trusted defaults 456 resetSettingsViaShell(type, 457 Settings.RESET_MODE_TRUSTED_DEFAULTS); 458 459 // Check whether snapped to trusted defaults 460 assertEquals(FAKE_SETTING_VALUE, getSetting(type, FAKE_SETTING_NAME)); 461 assertNull(getSetting(type, FAKE_SETTING_NAME_1)); 462 } finally { 463 // Make sure we have a clean slate. 464 putSetting(type, FAKE_SETTING_NAME, null); 465 setSettingViaShell(type, FAKE_SETTING_NAME_1, null, true); 466 } 467 } 468 doTestQueryStringInBracketsViaProviderApiForType(int type)469 private void doTestQueryStringInBracketsViaProviderApiForType(int type) { 470 // Make sure we have a clean slate. 471 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 472 473 try { 474 // Insert the setting. 475 final Uri uri = insertStringViaProviderApi(type, FAKE_SETTING_NAME, 476 FAKE_SETTING_VALUE, false); 477 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME); 478 assertEquals("Did not get expected Uri.", expectUri, uri); 479 480 // Make sure the first setting is there. 481 String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME, true, false); 482 assertEquals("Setting must be present", FAKE_SETTING_VALUE, firstValue); 483 } finally { 484 // Clean up. 485 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 486 } 487 } 488 toTestBulkInsertViaProviderApiForType(int type)489 private void toTestBulkInsertViaProviderApiForType(int type) { 490 // Make sure we have a clean slate. 491 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 492 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1); 493 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2); 494 495 try { 496 Uri uri = getBaseUriForType(type); 497 ContentValues[] allValues = new ContentValues[3]; 498 499 // Insert the first setting. 500 ContentValues firstValues = new ContentValues(); 501 firstValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME); 502 firstValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE); 503 allValues[0] = firstValues; 504 505 // Insert the second setting. 506 ContentValues secondValues = new ContentValues(); 507 secondValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_1); 508 secondValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_1); 509 allValues[1] = secondValues; 510 511 // Insert the third setting. (null) 512 ContentValues thirdValues = new ContentValues(); 513 thirdValues.put(Settings.NameValueTable.NAME, FAKE_SETTING_NAME_2); 514 thirdValues.put(Settings.NameValueTable.VALUE, FAKE_SETTING_VALUE_2); 515 allValues[2] = thirdValues; 516 517 // Verify insertion count. 518 final int insertCount = getContext().getContentResolver().bulkInsert(uri, allValues); 519 assertSame("Couldn't insert both values", 3, insertCount); 520 521 // Make sure the first setting is there. 522 String firstValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 523 assertEquals("First setting must be present", FAKE_SETTING_VALUE, firstValue); 524 525 // Make sure the second setting is there. 526 String secondValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_1); 527 assertEquals("Second setting must be present", FAKE_SETTING_VALUE_1, secondValue); 528 529 // Make sure the third setting is there. 530 String thirdValue = queryStringViaProviderApi(type, FAKE_SETTING_NAME_2); 531 assertEquals("Third setting must be present", FAKE_SETTING_VALUE_2, thirdValue); 532 } finally { 533 // Clean up. 534 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 535 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_1); 536 deleteStringViaProviderApi(type, FAKE_SETTING_NAME_2); 537 } 538 } 539 doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type)540 private void doTestQueryUpdateDeleteGlobalViaProviderApiForType(int type) throws Exception { 541 // Make sure it is not there. 542 deleteStringViaProviderApi(type, FAKE_SETTING_NAME); 543 544 // Now selection should return nothing. 545 String value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 546 assertNull("Setting should not be present.", value); 547 548 // Insert the setting. 549 Uri uri = insertStringViaProviderApi(type, 550 FAKE_SETTING_NAME, FAKE_SETTING_VALUE, false); 551 Uri expectUri = Uri.withAppendedPath(getBaseUriForType(type), FAKE_SETTING_NAME); 552 assertEquals("Did not get expected Uri.", expectUri, uri); 553 554 // Now selection should return the setting. 555 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 556 assertEquals("Setting should be present.", FAKE_SETTING_VALUE, value); 557 558 // Update the setting. 559 final int changeCount = updateStringViaProviderApiSetting(type, 560 FAKE_SETTING_NAME, FAKE_SETTING_VALUE_1); 561 assertEquals("Did not get expected change count.", 1, changeCount); 562 563 // Now selection should return the new setting. 564 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 565 assertEquals("Setting should be present.", FAKE_SETTING_VALUE_1, value); 566 567 // Delete the setting. 568 final int deletedCount = deleteStringViaProviderApi(type, 569 FAKE_SETTING_NAME); 570 assertEquals("Did not get expected deleted count", 1, deletedCount); 571 572 // Now selection should return nothing. 573 value = queryStringViaProviderApi(type, FAKE_SETTING_NAME); 574 assertNull("Setting should not be present.", value); 575 } 576 performSetAndGetSettingTestViaFrontEndApi(int type, int userId)577 private void performSetAndGetSettingTestViaFrontEndApi(int type, int userId) 578 throws Exception { 579 try { 580 // Change the setting and assert a successful change. 581 setSettingViaFrontEndApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, 582 FAKE_SETTING_VALUE, userId); 583 } finally { 584 // Remove the setting. 585 setStringViaFrontEndApiSetting(type, FAKE_SETTING_NAME, null, userId); 586 } 587 } 588 performSetAndGetSettingTestViaProviderApi(int type)589 private void performSetAndGetSettingTestViaProviderApi(int type) 590 throws Exception { 591 try { 592 // Change the setting and assert a successful change. 593 setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, 594 FAKE_SETTING_VALUE, true); 595 } finally { 596 // Remove the setting. 597 setSettingViaProviderApiAndAssertSuccessfulChange(type, FAKE_SETTING_NAME, null, 598 true); 599 } 600 } 601 setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, final String name, final String value, final int userId)602 private void setSettingViaFrontEndApiAndAssertSuccessfulChange(final int type, 603 final String name, final String value, final int userId) throws Exception { 604 setSettingAndAssertSuccessfulChange(() -> { 605 setStringViaFrontEndApiSetting(type, name, value, userId); 606 }, type, name, value, userId); 607 } 608 setSettingViaProviderApiAndAssertSuccessfulChange(final int type, final String name, final String value, final boolean withTableRowUri)609 private void setSettingViaProviderApiAndAssertSuccessfulChange(final int type, 610 final String name, final String value, final boolean withTableRowUri) 611 throws Exception { 612 setSettingAndAssertSuccessfulChange(() -> { 613 insertStringViaProviderApi(type, name, value, withTableRowUri); 614 }, type, name, value, UserHandle.USER_SYSTEM); 615 } 616 setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, final String name, final String value, final int userId)617 private void setSettingAndAssertSuccessfulChange(Runnable setCommand, final int type, 618 final String name, final String value, final int userId) throws Exception { 619 ContentResolver contentResolver = getContext().getContentResolver(); 620 621 final Uri settingUri = getBaseUriForType(type).buildUpon().appendPath(name).build(); 622 623 final AtomicBoolean success = new AtomicBoolean(); 624 625 ContentObserver contentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { 626 public void onChange(boolean selfChange, Uri changeUri, int changeId) { 627 Log.i(LOG_TAG, "onChange(" + selfChange + ", " + changeUri + ", " + changeId + ")"); 628 assertEquals("Wrong change Uri", changeUri, settingUri); 629 assertEquals("Wrong user id", userId, changeId); 630 String changeValue = getStringViaFrontEndApiSetting(type, name, userId); 631 assertEquals("Wrong setting value", value, changeValue); 632 633 success.set(true); 634 635 synchronized (mLock) { 636 mLock.notifyAll(); 637 } 638 } 639 }; 640 641 contentResolver.registerContentObserver(settingUri, false, contentObserver, userId); 642 643 try { 644 setCommand.run(); 645 646 final long startTimeMillis = SystemClock.uptimeMillis(); 647 synchronized (mLock) { 648 while (true) { 649 if (success.get()) { 650 return; 651 } 652 final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis; 653 if (elapsedTimeMillis >= WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS) { 654 fail("Could not change setting for " 655 + WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS + " ms"); 656 } 657 final long remainingTimeMillis = WAIT_FOR_SETTING_URI_CHANGE_TIMEOUT_MILLIS 658 - elapsedTimeMillis; 659 try { 660 mLock.wait(remainingTimeMillis); 661 } catch (InterruptedException ie) { 662 /* ignore */ 663 } 664 } 665 } 666 } finally { 667 contentResolver.unregisterContentObserver(contentObserver); 668 } 669 } 670 queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, String name)671 private void queryAllSettingsViaProviderApiSettingAndAssertSettingPresent(int type, 672 String name) { 673 Uri uri = getBaseUriForType(type); 674 675 Cursor cursor = getContext().getContentResolver().query(uri, NAME_VALUE_COLUMNS, 676 null, null, null); 677 678 if (cursor == null || !cursor.moveToFirst()) { 679 fail("Nothing selected"); 680 } 681 682 try { 683 final int nameColumnIdx = cursor.getColumnIndex(Settings.NameValueTable.NAME); 684 685 while (cursor.moveToNext()) { 686 String currentName = cursor.getString(nameColumnIdx); 687 if (name.equals(currentName)) { 688 return; 689 } 690 } 691 692 fail("Not found setting: " + name); 693 } finally { 694 cursor.close(); 695 } 696 } 697 } 698