Guard against incorrect context use.

Instead of just having random tests fail, fail all the tests with a
slightly more useful message.

Also remove all the code around acquiring and contention, now that
we have a test rule in place for TestableContext, we can just use
that for cleanup and have a simple copy-on-write provider.

Test: runtest -x frameworks/base/tests/testables && runtest systemui
Change-Id: I907da23730a4a96cfa2bb112100a06980f01b078
Fixes: 37302051
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java
index cb5d4cb..630a287 100644
--- a/tests/testables/src/android/testing/TestableContext.java
+++ b/tests/testables/src/android/testing/TestableContext.java
@@ -43,7 +43,7 @@
  * <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 @@
 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 @@
         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 @@
         return super.getSystemService(name);
     }
 
-    public TestableSettings getSettingsProvider() {
+    TestableSettingsProvider getSettingsProvider() {
         return mSettingsProvider;
     }
 
@@ -236,12 +235,12 @@
         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 d19f1ef..0000000
--- 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 0000000..13056cf
--- /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 0000000..1f71867
--- /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 1b01542..0000000
--- 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;
-    }
-}