diff options
7 files changed, 222 insertions, 509 deletions
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java index 048936b3f5f0..bbe324d7d8d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationTest.java @@ -47,9 +47,8 @@ public class DozeConfigurationTest extends SysuiTestCase { return; } - mContext.getSettingsProvider().acquireOverridesBuilder() - .addSetting("secure", Settings.Secure.DOZE_ALWAYS_ON, null) - .build(); + Settings.Secure.putString(mContext.getContentResolver(), Settings.Secure.DOZE_ALWAYS_ON, + null); assertFalse(mDozeConfig.alwaysOnEnabled(UserHandle.USER_CURRENT)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java index edfa3261a7e8..9fd3832c0b78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerWifiTest.java @@ -18,7 +18,6 @@ import android.test.suitebuilder.annotation.SmallTest; import com.android.settingslib.Utils; import com.android.systemui.statusbar.policy.NetworkController.IconState; -import android.testing.TestableSettings.SettingOverrider; import org.junit.Test; import org.junit.runner.RunWith; @@ -92,11 +91,10 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { attr); // Must set the Settings value before instantiating the NetworkControllerImpl due to bugs in - // TestableSettings. - SettingOverrider settingsOverrider = - mContext.getSettingsProvider().acquireOverridesBuilder() - .addSetting("global", Settings.Global.NETWORK_SCORING_UI_ENABLED, "1") - .build(); + // TestableSettingsProvider. + Settings.Global.putString(mContext.getContentResolver(), + Settings.Global.NETWORK_SCORING_UI_ENABLED, + "1"); super.setUp(); // re-instantiate NetworkControllImpl now that setting has been updated setupNetworkScoreManager(); @@ -131,8 +129,6 @@ public class NetworkControllerWifiTest extends NetworkControllerBaseTest { assertEquals("SD Badge is set", Utils.getWifiBadgeResource(NetworkBadging.BADGING_SD), iconState.iconOverlay); - - settingsOverrider.release(); } private void setupNetworkScoreManager() { diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java index cb5d4cb8242f..630a287c6f4a 100644 --- a/tests/testables/src/android/testing/TestableContext.java +++ b/tests/testables/src/android/testing/TestableContext.java @@ -43,7 +43,7 @@ import org.junit.runners.model.Statement; * <ul> * <li>System services can be mocked out with {@link #addMockSystemService}</li> * <li>Service binding can be mocked out with {@link #addMockService}</li> - * <li>Settings support {@link TestableSettings}</li> + * <li>Settings support {@link TestableSettingsProvider}</li> * <li>Has support for {@link LeakCheck} for services and receivers</li> * </ul> * @@ -59,7 +59,7 @@ import org.junit.runners.model.Statement; public class TestableContext extends ContextWrapper implements TestRule { private final TestableContentResolver mTestableContentResolver; - private final TestableSettings mSettingsProvider; + private final TestableSettingsProvider mSettingsProvider; private ArrayMap<String, Object> mMockSystemServices; private ArrayMap<ComponentName, IBinder> mMockServices; @@ -79,9 +79,8 @@ public class TestableContext extends ContextWrapper implements TestRule { mTestableContentResolver = new TestableContentResolver(base); ContentProviderClient settings = base.getContentResolver() .acquireContentProviderClient(Settings.AUTHORITY); - mSettingsProvider = TestableSettings.getFakeSettingsProvider(settings, - mTestableContentResolver); - mTestableContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider.getProvider()); + mSettingsProvider = TestableSettingsProvider.getFakeSettingsProvider(settings); + mTestableContentResolver.addProvider(Settings.AUTHORITY, mSettingsProvider); mReceiver = check != null ? check.getTracker("receiver") : null; mService = check != null ? check.getTracker("service") : null; mComponent = check != null ? check.getTracker("component") : null; @@ -129,7 +128,7 @@ public class TestableContext extends ContextWrapper implements TestRule { return super.getSystemService(name); } - public TestableSettings getSettingsProvider() { + TestableSettingsProvider getSettingsProvider() { return mSettingsProvider; } @@ -236,12 +235,12 @@ public class TestableContext extends ContextWrapper implements TestRule { return new TestWatcher() { @Override protected void succeeded(Description description) { - mSettingsProvider.clearOverrides(); + mSettingsProvider.clearValuesAndCheck(TestableContext.this); } @Override protected void failed(Throwable e, Description description) { - mSettingsProvider.clearOverrides(); + mSettingsProvider.clearValuesAndCheck(TestableContext.this); } }.apply(base, description); } diff --git a/tests/testables/src/android/testing/TestableSettings.java b/tests/testables/src/android/testing/TestableSettings.java deleted file mode 100644 index d19f1ef60b2e..000000000000 --- a/tests/testables/src/android/testing/TestableSettings.java +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package android.testing; - -import android.content.ContentProvider; -import android.content.ContentProviderClient; -import android.content.ContentResolver; -import android.os.Bundle; -import android.os.RemoteException; -import android.provider.Settings; -import android.support.annotation.VisibleForTesting; -import android.test.mock.MockContentProvider; -import android.testing.TestableSettings.SettingOverrider.Builder; -import android.util.ArrayMap; -import android.util.ArraySet; -import android.util.Log; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Allows calls to android.provider.Settings to be tested easier. A SettingOverride - * can be acquired and a set of specific settings can be set to a value (and not changed - * in the system when set), so that they can be tested without breaking the test device. - * <p> - * To use, in the before method acquire the override add all settings that will affect if - * your test passes or not. - * - * <pre class="prettyprint"> - * {@literal - * mSettingOverride = mTestableContext.getSettingsProvider().acquireOverridesBuilder() - * .addSetting("secure", Secure.USER_SETUP_COMPLETE, "0") - * .build(); - * } - * </pre> - * - * Then in the after free up the settings. - * - * <pre class="prettyprint"> - * {@literal - * mSettingOverride.release(); - * } - * </pre> - */ -public class TestableSettings { - - private static final String TAG = "TestableSettings"; - private static final boolean DEBUG = false; - - // Number of times to try to acquire a setting if in use. - private static final int MAX_TRIES = 10; - // Time to wait for each setting. WAIT_TIMEOUT * MAX_TRIES will be the maximum wait time - // for a setting. - private static final long WAIT_TIMEOUT = 1000; - - private static TestableSettingsProvider sInstance; - - private final TestableSettingsProvider mProvider; - - private TestableSettings(TestableSettingsProvider provider) { - mProvider = provider; - } - - public Builder acquireOverridesBuilder() { - return new Builder(this); - } - - public void clearOverrides() { - List<SettingOverrider> overrides = mProvider.mOwners.remove(this); - if (overrides != null) { - overrides.forEach(override -> override.ensureReleased()); - } - } - - private void acquireSettings(SettingOverrider overridder, Set<String> keys) - throws AcquireTimeoutException { - mProvider.acquireSettings(overridder, keys, this); - } - - ContentProvider getProvider() { - return mProvider; - } - - @VisibleForTesting - Object getLock() { - return mProvider.mOverrideMap; - } - - public static class SettingOverrider { - private final Set<String> mValidKeys; - private final Map<String, String> mValueMap = new ArrayMap<>(); - private final TestableSettings mSettings; - private boolean mReleased; - public Throwable mObtain; - - private SettingOverrider(Set<String> keys, TestableSettings provider) { - mValidKeys = new ArraySet<>(keys); - mSettings = provider; - } - - private void ensureReleased() { - if (!mReleased) { - release(); - } - } - - public void release() { - mSettings.mProvider.releaseSettings(mValidKeys); - mReleased = true; - } - - private void putDirect(String key, String value) { - mValueMap.put(key, value); - } - - public void put(String table, String key, String value) { - if (!mValidKeys.contains(key(table, key))) { - throw new IllegalArgumentException("Key " + table + " " + key - + " not acquired for this overrider"); - } - mValueMap.put(key(table, key), value); - } - - public void remove(String table, String key) { - if (!mValidKeys.contains(key(table, key))) { - throw new IllegalArgumentException("Key " + table + " " + key - + " not acquired for this overrider"); - } - mValueMap.remove(key(table, key)); - } - - public String get(String table, String key) { - if (!mValidKeys.contains(key(table, key))) { - throw new IllegalArgumentException("Key " + table + " " + key - + " not acquired for this overrider"); - } - Log.d(TAG, "Get " + table + " " + key + " " + mValueMap.get(key(table, key))); - return mValueMap.get(key(table, key)); - } - - public static class Builder { - private final TestableSettings mProvider; - private Set<String> mKeys = new ArraySet<>(); - private Map<String, String> mValues = new ArrayMap<>(); - - private Builder(TestableSettings provider) { - mProvider = provider; - } - - public Builder addSetting(String table, String key) { - mKeys.add(key(table, key)); - return this; - } - - public Builder addSetting(String table, String key, String value) { - addSetting(table, key); - mValues.put(key(table, key), value); - return this; - } - - public SettingOverrider build() throws AcquireTimeoutException { - SettingOverrider overrider = new SettingOverrider(mKeys, mProvider); - mProvider.acquireSettings(overrider, mKeys); - mValues.forEach((key, value) -> overrider.putDirect(key, value)); - return overrider; - } - } - } - - private static class TestableSettingsProvider extends MockContentProvider { - - private final Map<String, SettingOverrider> mOverrideMap = new ArrayMap<>(); - private final Map<Object, List<SettingOverrider>> mOwners = new ArrayMap<>(); - - private final ContentProviderClient mSettings; - private final ContentResolver mResolver; - - public TestableSettingsProvider(ContentProviderClient settings, ContentResolver resolver) { - mSettings = settings; - mResolver = resolver; - } - - private void releaseSettings(Set<String> keys) { - synchronized (mOverrideMap) { - for (String key : keys) { - if (DEBUG) Log.d(TAG, "Releasing " + key); - mOverrideMap.remove(key); - } - if (DEBUG) Log.d(TAG, "Notifying"); - mOverrideMap.notify(); - } - } - - private boolean checkKeysLocked(Set<String> keys, boolean shouldThrow) - throws AcquireTimeoutException { - for (String key : keys) { - if (mOverrideMap.containsKey(key)) { - if (shouldThrow) { - if (DEBUG) Log.e(TAG, "Lock obtained at", - mOverrideMap.get(key).mObtain); - throw new AcquireTimeoutException("Could not acquire " + key, - mOverrideMap.get(key).mObtain); - } - return false; - } - } - return true; - } - - private void acquireSettings(SettingOverrider overridder, Set<String> keys, - Object owner) throws AcquireTimeoutException { - synchronized (mOwners) { - List<SettingOverrider> list = mOwners.get(owner); - if (list == null) { - list = new ArrayList<>(); - mOwners.put(owner, list); - } - list.add(overridder); - } - synchronized (mOverrideMap) { - for (int i = 0; i < MAX_TRIES; i++) { - if (checkKeysLocked(keys, false)) break; - try { - if (DEBUG) Log.d(TAG, "Waiting for contention to finish"); - mOverrideMap.wait(WAIT_TIMEOUT); - } catch (InterruptedException e) { - } - } - overridder.mObtain = new Throwable(); - checkKeysLocked(keys, true); - for (String key : keys) { - if (DEBUG) Log.d(TAG, "Acquiring " + key); - mOverrideMap.put(key, overridder); - } - } - } - - public Bundle call(String method, String arg, Bundle extras) { - // Methods are "GET_system", "GET_global", "PUT_secure", etc. - final String[] commands = method.split("_", 2); - final String op = commands[0]; - final String table = commands[1]; - - synchronized (mOverrideMap) { - SettingOverrider overrider = mOverrideMap.get(key(table, arg)); - if (overrider == null) { - // Fall through to real settings. - try { - if (DEBUG) Log.d(TAG, "Falling through to real settings " + method); - // TODO: Add our own version of caching to handle this. - Bundle call = mSettings.call(method, arg, extras); - call.remove(Settings.CALL_METHOD_TRACK_GENERATION_KEY); - return call; - } catch (RemoteException e) { - throw new RuntimeException(e); - } - } - String value; - Bundle out = new Bundle(); - switch (op) { - case "GET": - value = overrider.get(table, arg); - if (value != null) { - out.putString(Settings.NameValueTable.VALUE, value); - } - break; - case "PUT": - value = extras.getString(Settings.NameValueTable.VALUE, null); - if (value != null) { - overrider.put(table, arg, value); - } else { - overrider.remove(table, arg); - } - break; - default: - throw new UnsupportedOperationException("Unknown command " + method); - } - return out; - } - } - } - - public static class AcquireTimeoutException extends Exception { - public AcquireTimeoutException(String str, Throwable cause) { - super(str, cause); - } - } - - private static String key(String table, String key) { - return table + "_" + key; - } - - /** - * Since the settings provider is cached inside android.provider.Settings, this must - * be gotten statically to ensure there is only one instance referenced. - */ - public static TestableSettings getFakeSettingsProvider(ContentProviderClient settings, - ContentResolver resolver) { - if (sInstance == null) { - sInstance = new TestableSettingsProvider(settings, resolver); - } - return new TestableSettings(sInstance); - } -} diff --git a/tests/testables/src/android/testing/TestableSettingsProvider.java b/tests/testables/src/android/testing/TestableSettingsProvider.java new file mode 100644 index 000000000000..13056cf677d6 --- /dev/null +++ b/tests/testables/src/android/testing/TestableSettingsProvider.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package android.testing; + +import android.content.ContentProviderClient; +import android.content.Context; +import android.os.Bundle; +import android.os.RemoteException; +import android.provider.Settings; +import android.test.mock.MockContentProvider; +import android.util.Log; + +import java.util.HashMap; + +import static org.junit.Assert.*; + +/** + * Allows calls to android.provider.Settings to be tested easier. + * + * This provides a simple copy-on-write implementation of settings that gets cleared + * at the end of each test. + */ +public class TestableSettingsProvider extends MockContentProvider { + + private static final String TAG = "TestableSettingsProvider"; + private static final boolean DEBUG = false; + private static final String MY_UNIQUE_KEY = "Key_" + TestableSettingsProvider.class.getName(); + private static TestableSettingsProvider sInstance; + + private final ContentProviderClient mSettings; + + private final HashMap<String, String> mValues = new HashMap<>(); + + private TestableSettingsProvider(ContentProviderClient settings) { + mSettings = settings; + } + + void clearValuesAndCheck(Context context) { + mValues.put(key("global", MY_UNIQUE_KEY), MY_UNIQUE_KEY); + mValues.put(key("secure", MY_UNIQUE_KEY), MY_UNIQUE_KEY); + mValues.put(key("system", MY_UNIQUE_KEY), MY_UNIQUE_KEY); + + // Verify that if any test is using TestableContext, they all have the correct settings + // provider. + assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY, + Settings.Global.getString(context.getContentResolver(), MY_UNIQUE_KEY)); + assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY, + Settings.Secure.getString(context.getContentResolver(), MY_UNIQUE_KEY)); + assertEquals("Incorrect settings provider, test using incorrect Context?", MY_UNIQUE_KEY, + Settings.System.getString(context.getContentResolver(), MY_UNIQUE_KEY)); + + mValues.clear(); + } + + public Bundle call(String method, String arg, Bundle extras) { + // Methods are "GET_system", "GET_global", "PUT_secure", etc. + final String[] commands = method.split("_", 2); + final String op = commands[0]; + final String table = commands[1]; + + String k = key(table, arg); + String value; + Bundle out = new Bundle(); + switch (op) { + case "GET": + if (mValues.containsKey(k)) { + value = mValues.get(k); + if (value != null) { + out.putString(Settings.NameValueTable.VALUE, value); + } + } else { + // Fall through to real settings. + try { + if (DEBUG) Log.d(TAG, "Falling through to real settings " + method); + // TODO: Add our own version of caching to handle this. + Bundle call = mSettings.call(method, arg, extras); + call.remove(Settings.CALL_METHOD_TRACK_GENERATION_KEY); + return call; + } catch (RemoteException e) { + throw new RuntimeException(e); + } + } + break; + case "PUT": + value = extras.getString(Settings.NameValueTable.VALUE, null); + mValues.put(k, value); + break; + default: + throw new UnsupportedOperationException("Unknown command " + method); + } + return out; + } + + private static String key(String table, String key) { + return table + "_" + key; + } + + /** + * Since the settings provider is cached inside android.provider.Settings, this must + * be gotten statically to ensure there is only one instance referenced. + */ + static TestableSettingsProvider getFakeSettingsProvider(ContentProviderClient settings) { + if (sInstance == null) { + sInstance = new TestableSettingsProvider(settings); + } + return sInstance; + } +} diff --git a/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java b/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java new file mode 100644 index 000000000000..1f71867396ab --- /dev/null +++ b/tests/testables/tests/src/android/testing/TestableSettingsProviderTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the + * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the specific language governing + * permissions and limitations under the License. + */ + +package android.testing; + +import android.content.ContentResolver; +import android.provider.Settings; +import android.provider.Settings.Global; +import android.provider.Settings.Secure; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +@RunWith(AndroidJUnit4.class) +public class TestableSettingsProviderTest { + + public static final String NONEXISTENT_SETTING = "nonexistent_setting"; + private static final String TAG = "TestableSettingsProviderTest"; + private ContentResolver mContentResolver; + @Rule + public final TestableContext mContext = + new TestableContext(InstrumentationRegistry.getContext()); + + @Before + public void setup() { + mContentResolver = mContext.getContentResolver(); + Settings.Secure.putString(mContentResolver, NONEXISTENT_SETTING, null); + Settings.Global.putString(mContentResolver, NONEXISTENT_SETTING, "initial value"); + Settings.Global.putString(mContentResolver, Global.DEVICE_PROVISIONED, null); + } + + @Test + public void testInitialValueSecure() { + String value = Secure.getString(mContentResolver, NONEXISTENT_SETTING); + assertNull(value); + } + + @Test + public void testInitialValueGlobal() { + String value = Global.getString(mContentResolver, NONEXISTENT_SETTING); + assertEquals("initial value", value); + } + + @Test + public void testSeparateTables() { + Secure.putString(mContentResolver, NONEXISTENT_SETTING, "something"); + Global.putString(mContentResolver, NONEXISTENT_SETTING, "else"); + assertEquals("something", Secure.getString(mContentResolver, NONEXISTENT_SETTING)); + assertEquals("else", Global.getString(mContentResolver, NONEXISTENT_SETTING)); + } + + @Test + public void testPassThrough() { + // Grab the value of a setting that is not overridden. + assertTrue(Secure.getInt(mContentResolver, Secure.USER_SETUP_COMPLETE, 0) != 0); + } + + @Test + public void testOverrideExisting() { + // Grab the value of a setting that is overridden and will be different than the actual + // value. + assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED)); + } + + @Test + public void testRelease() { + // Verify different value. + assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED)); + mContext.getSettingsProvider().clearValuesAndCheck(mContext); + // Verify actual value after release. + assertEquals("1", Global.getString(mContentResolver, Global.DEVICE_PROVISIONED)); + } +} diff --git a/tests/testables/tests/src/android/testing/TestableSettingsTest.java b/tests/testables/tests/src/android/testing/TestableSettingsTest.java deleted file mode 100644 index 1b01542a8a64..000000000000 --- a/tests/testables/tests/src/android/testing/TestableSettingsTest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the specific language governing - * permissions and limitations under the License. - */ - -package android.testing; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -import android.content.ContentResolver; -import android.os.Handler; -import android.os.HandlerThread; -import android.provider.Settings; -import android.provider.Settings.Global; -import android.provider.Settings.Secure; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; -import android.testing.TestableSettings.AcquireTimeoutException; -import android.testing.TestableSettings.SettingOverrider; -import android.util.Log; - -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class TestableSettingsTest { - - public static final String NONEXISTENT_SETTING = "nonexistent_setting"; - private static final String TAG = "TestableSettingsTest"; - private SettingOverrider mOverrider; - private ContentResolver mContentResolver; - @Rule - public final TestableContext mContext = - new TestableContext(InstrumentationRegistry.getContext()); - - @Before - public void setup() throws AcquireTimeoutException { - mOverrider = mContext.getSettingsProvider().acquireOverridesBuilder() - .addSetting("secure", NONEXISTENT_SETTING) - .addSetting("global", NONEXISTENT_SETTING, "initial value") - .addSetting("global", Global.DEVICE_PROVISIONED) - .build(); - mContentResolver = mContext.getContentResolver(); - } - - @Test - public void testInitialValueSecure() { - String value = Secure.getString(mContentResolver, NONEXISTENT_SETTING); - assertNull(value); - } - - @Test - public void testInitialValueGlobal() { - String value = Global.getString(mContentResolver, NONEXISTENT_SETTING); - assertEquals("initial value", value); - } - - @Test - public void testSeparateTables() { - Secure.putString(mContentResolver, NONEXISTENT_SETTING, "something"); - Global.putString(mContentResolver, NONEXISTENT_SETTING, "else"); - assertEquals("something", Secure.getString(mContentResolver, NONEXISTENT_SETTING)); - assertEquals("something", mOverrider.get("secure", NONEXISTENT_SETTING)); - assertEquals("else", Global.getString(mContentResolver, NONEXISTENT_SETTING)); - assertEquals("else", mOverrider.get("global", NONEXISTENT_SETTING)); - } - - @Test - public void testPassThrough() { - // Grab the value of a setting that is not overridden. - assertTrue(Secure.getInt(mContentResolver, Secure.USER_SETUP_COMPLETE, 0) != 0); - } - - @Test - public void testOverrideExisting() { - // Grab the value of a setting that is overridden and will be different than the actual - // value. - assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED)); - } - - @Test - public void testRelease() { - // Verify different value. - assertNull(Global.getString(mContentResolver, Global.DEVICE_PROVISIONED)); - mOverrider.release(); - mOverrider = null; - // Verify actual value after release. - assertEquals("1", Global.getString(mContentResolver, Global.DEVICE_PROVISIONED)); - } - - @Test - public void testAutoRelease() throws Exception { - mOverrider.release(); - mOverrider = null; - mContext.getSettingsProvider().acquireOverridesBuilder() - .addSetting("global", Global.DEVICE_PROVISIONED) - .build(); - } - - @Test - public void testContention() throws AcquireTimeoutException, InterruptedException { - SettingOverrider[] overriders = new SettingOverrider[2]; - Object lock = new Object(); - String secure = "secure"; - String key = "something shared"; - String[] result = new String[1]; - overriders[0] = mContext.getSettingsProvider().acquireOverridesBuilder() - .addSetting(secure, key, "Some craziness") - .build(); - synchronized (lock) { - HandlerThread t = runOnHandler(() -> { - try { - // Grab the lock that will be used for the settings ownership to ensure - // we have some contention going on. - synchronized (mContext.getSettingsProvider().getLock()) { - synchronized (lock) { - // Let the other thread know to release the settings, but it won't - // be able to until this thread waits in the build() method. - lock.notify(); - } - overriders[1] = mContext.getSettingsProvider() - .acquireOverridesBuilder() - .addSetting(secure, key, "default value") - .build(); - // Ensure that the default is the one we set, and not left over from - // the other setting override. - result[0] = Settings.Secure.getString(mContentResolver, key); - synchronized (lock) { - // Let the main thread know we are done. - lock.notify(); - } - } - } catch (AcquireTimeoutException e) { - Log.e(TAG, "Couldn't acquire setting", e); - } - }); - // Wait for the thread to hold the acquire lock, then release the settings. - lock.wait(); - overriders[0].release(); - // Wait for the thread to be done getting the value. - lock.wait(); - // Quit and cleanup. - t.quitSafely(); - assertNotNull(overriders[1]); - overriders[1].release(); - } - // Verify the value was the expected one from the thread's SettingOverride. - assertEquals("default value", result[0]); - } - - private HandlerThread runOnHandler(Runnable r) { - HandlerThread t = new HandlerThread("Test Thread"); - t.start(); - new Handler(t.getLooper()).post(r); - return t; - } -} |