Loading core/tests/utiltests/src/com/android/internal/util/test/FakeSettingsProviderTest.java +52 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.internal.util.test; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertEquals; Loading @@ -37,6 +38,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; /** * Unit tests for FakeSettingsProvider. */ Loading @@ -52,10 +55,13 @@ public class FakeSettingsProviderTest { private MockContentResolver mCr; private ArrayList<String> mCallbacks; @Before public void setUp() throws Exception { FakeSettingsProvider.clearSettingsProvider(); mCr = new MockContentResolver(); mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mCallbacks = new ArrayList<>(); } private void assertSystemSettingNotFound(String name) { Loading @@ -70,6 +76,7 @@ public class FakeSettingsProviderTest { @Test @SmallTest public void testBasicOperation() throws Exception { mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); assertSystemSettingNotFound(SYSTEM_SETTING); // Check that fake settings can be written and read back. Loading Loading @@ -101,6 +108,7 @@ public class FakeSettingsProviderTest { @Test @SmallTest public void testMultiUserOperation() { mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "user0Setting", 0); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "user1Setting", 1); assertEquals("user0Setting", Settings.Secure.getStringForUser(mCr, SECURE_SETTING, 0)); Loading Loading @@ -135,4 +143,47 @@ public class FakeSettingsProviderTest { assertEquals("newGlobalSetting", Settings.Global.getStringForUser(mCr, GLOBAL_SETTING, 42)); } private void assertCallbackReceived(String expectedCallback) { assertFalse("No callbacks received", mCallbacks.isEmpty()); assertEquals(expectedCallback, mCallbacks.removeFirst()); } private void assertNoCallbackReceived() { assertEquals(0, mCallbacks.size()); } @Test @SmallTest public void testCallbacks() { mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider((userId, uri) -> mCallbacks.add(userId + ":" + uri.toString()))); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "value", 1); assertCallbackReceived("1:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "newvalue", 1); assertCallbackReceived("1:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "value", 2); assertCallbackReceived("2:content://settings/secure/bluetooth_name"); // Callback is not called if value doesn't change. Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "newvalue", 1); assertNoCallbackReceived(); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, null, 2); assertCallbackReceived("2:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, null, 1); assertCallbackReceived("1:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, null, 1); assertNoCallbackReceived(); final int currentUserId = UserHandle.getUserId(Process.myUid()); Settings.System.putString(mCr, SYSTEM_SETTING, "value"); assertCallbackReceived(currentUserId + ":" + "content://settings/system/screen_brightness"); } } tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java +19 −9 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.internal.util.test; import android.annotation.NonNull; import android.net.Uri; import android.os.Bundle; import android.os.UserHandle; Loading @@ -25,6 +26,7 @@ import android.util.ArrayMap; import android.util.Log; import java.util.Map; import java.util.Objects; /** * Fake for system settings. Loading Loading @@ -58,13 +60,6 @@ import java.util.Map; * class only fetches the content provider from the passed-in ContentResolver the first time it's * used, and after that stores it in a per-process static. If this needs to be used in this case, * then call {@link #clearSettingsProvider()} before and after using this. * * TODO: evaluate implementing settings change notifications. This would require: * * 1. Making ContentResolver#registerContentObserver non-final and overriding it in * MockContentResolver. * 2. Making FakeSettingsProvider take a ContentResolver argument. * 3. Calling ContentResolver#notifyChange(getUriFor(table, arg), ...) on every settings change. */ public class FakeSettingsProvider extends MockContentProvider { Loading @@ -81,10 +76,23 @@ public class FakeSettingsProvider extends MockContentProvider { */ private final Map<String, Map<Integer, Map<String, String>>> mDb = new ArrayMap<>(); public FakeSettingsProvider() { public interface Callback { /** Called whenever a setting's value changes. */ void onUriChanged(int userId, Uri uri); } private final Callback mCallback; public FakeSettingsProvider(@NonNull Callback callback) { Objects.requireNonNull(callback); for (int i = 0; i < TABLES.length; i++) { mDb.put(TABLES[i], new ArrayMap<>()); } mCallback = callback; } public FakeSettingsProvider() { this((user, uri) -> {}); } private Uri getUriFor(String table, String key) { Loading Loading @@ -160,7 +168,8 @@ public class FakeSettingsProvider extends MockContentProvider { value = extras.getString(Settings.NameValueTable.VALUE, null); final boolean changed; if (value != null) { changed = !value.equals(mDb.get(table) changed = !value.equals( mDb.get(table) .computeIfAbsent(userId, (u) -> new ArrayMap<>()) .put(arg, value)); if (DBG) { Loading @@ -175,6 +184,7 @@ public class FakeSettingsProvider extends MockContentProvider { arg)); } } if (changed) mCallback.onUriChanged(userId, getUriFor(table, arg)); break; default: throw new UnsupportedOperationException("Unknown command " + method); Loading Loading
core/tests/utiltests/src/com/android/internal/util/test/FakeSettingsProviderTest.java +52 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.internal.util.test; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNull; import static org.junit.Assert.assertEquals; Loading @@ -37,6 +38,8 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import java.util.ArrayList; /** * Unit tests for FakeSettingsProvider. */ Loading @@ -52,10 +55,13 @@ public class FakeSettingsProviderTest { private MockContentResolver mCr; private ArrayList<String> mCallbacks; @Before public void setUp() throws Exception { FakeSettingsProvider.clearSettingsProvider(); mCr = new MockContentResolver(); mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); mCallbacks = new ArrayList<>(); } private void assertSystemSettingNotFound(String name) { Loading @@ -70,6 +76,7 @@ public class FakeSettingsProviderTest { @Test @SmallTest public void testBasicOperation() throws Exception { mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); assertSystemSettingNotFound(SYSTEM_SETTING); // Check that fake settings can be written and read back. Loading Loading @@ -101,6 +108,7 @@ public class FakeSettingsProviderTest { @Test @SmallTest public void testMultiUserOperation() { mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider()); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "user0Setting", 0); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "user1Setting", 1); assertEquals("user0Setting", Settings.Secure.getStringForUser(mCr, SECURE_SETTING, 0)); Loading Loading @@ -135,4 +143,47 @@ public class FakeSettingsProviderTest { assertEquals("newGlobalSetting", Settings.Global.getStringForUser(mCr, GLOBAL_SETTING, 42)); } private void assertCallbackReceived(String expectedCallback) { assertFalse("No callbacks received", mCallbacks.isEmpty()); assertEquals(expectedCallback, mCallbacks.removeFirst()); } private void assertNoCallbackReceived() { assertEquals(0, mCallbacks.size()); } @Test @SmallTest public void testCallbacks() { mCr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider((userId, uri) -> mCallbacks.add(userId + ":" + uri.toString()))); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "value", 1); assertCallbackReceived("1:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "newvalue", 1); assertCallbackReceived("1:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "value", 2); assertCallbackReceived("2:content://settings/secure/bluetooth_name"); // Callback is not called if value doesn't change. Settings.Secure.putStringForUser(mCr, SECURE_SETTING, "newvalue", 1); assertNoCallbackReceived(); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, null, 2); assertCallbackReceived("2:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, null, 1); assertCallbackReceived("1:content://settings/secure/bluetooth_name"); Settings.Secure.putStringForUser(mCr, SECURE_SETTING, null, 1); assertNoCallbackReceived(); final int currentUserId = UserHandle.getUserId(Process.myUid()); Settings.System.putString(mCr, SYSTEM_SETTING, "value"); assertCallbackReceived(currentUserId + ":" + "content://settings/system/screen_brightness"); } }
tests/utils/testutils/java/com/android/internal/util/test/FakeSettingsProvider.java +19 −9 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.internal.util.test; import android.annotation.NonNull; import android.net.Uri; import android.os.Bundle; import android.os.UserHandle; Loading @@ -25,6 +26,7 @@ import android.util.ArrayMap; import android.util.Log; import java.util.Map; import java.util.Objects; /** * Fake for system settings. Loading Loading @@ -58,13 +60,6 @@ import java.util.Map; * class only fetches the content provider from the passed-in ContentResolver the first time it's * used, and after that stores it in a per-process static. If this needs to be used in this case, * then call {@link #clearSettingsProvider()} before and after using this. * * TODO: evaluate implementing settings change notifications. This would require: * * 1. Making ContentResolver#registerContentObserver non-final and overriding it in * MockContentResolver. * 2. Making FakeSettingsProvider take a ContentResolver argument. * 3. Calling ContentResolver#notifyChange(getUriFor(table, arg), ...) on every settings change. */ public class FakeSettingsProvider extends MockContentProvider { Loading @@ -81,10 +76,23 @@ public class FakeSettingsProvider extends MockContentProvider { */ private final Map<String, Map<Integer, Map<String, String>>> mDb = new ArrayMap<>(); public FakeSettingsProvider() { public interface Callback { /** Called whenever a setting's value changes. */ void onUriChanged(int userId, Uri uri); } private final Callback mCallback; public FakeSettingsProvider(@NonNull Callback callback) { Objects.requireNonNull(callback); for (int i = 0; i < TABLES.length; i++) { mDb.put(TABLES[i], new ArrayMap<>()); } mCallback = callback; } public FakeSettingsProvider() { this((user, uri) -> {}); } private Uri getUriFor(String table, String key) { Loading Loading @@ -160,7 +168,8 @@ public class FakeSettingsProvider extends MockContentProvider { value = extras.getString(Settings.NameValueTable.VALUE, null); final boolean changed; if (value != null) { changed = !value.equals(mDb.get(table) changed = !value.equals( mDb.get(table) .computeIfAbsent(userId, (u) -> new ArrayMap<>()) .put(arg, value)); if (DBG) { Loading @@ -175,6 +184,7 @@ public class FakeSettingsProvider extends MockContentProvider { arg)); } } if (changed) mCallback.onUriChanged(userId, getUriFor(table, arg)); break; default: throw new UnsupportedOperationException("Unknown command " + method); Loading