OSDN Git Service

Add Slider template for Slices
authorMatthew Fritze <mfritze@google.com>
Tue, 6 Feb 2018 22:13:02 +0000 (14:13 -0800)
committerMatthew Fritze <mfritze@google.com>
Thu, 22 Mar 2018 18:46:47 +0000 (11:46 -0700)
Add the Seekbar preference equivalent
to the TwoStatePreference (toggle) preference
controller abstract controller.

Change-Id: I6ff91f2f72a7f72c18ddbc27b2b1fda4b6ce6ca9
Fixes: 67996707
Test: Robotests

src/com/android/settings/core/SliderPreferenceController.java [new file with mode: 0644]
src/com/android/settings/core/TogglePreferenceController.java
src/com/android/settings/slices/SettingsSliceProvider.java
src/com/android/settings/slices/SliceBroadcastReceiver.java
src/com/android/settings/slices/SliceBuilderUtils.java
tests/robotests/src/com/android/settings/core/SliderPreferenceControllerTest.java [new file with mode: 0644]
tests/robotests/src/com/android/settings/slices/SliceBroadcastReceiverTest.java
tests/robotests/src/com/android/settings/slices/SliceBuilderUtilsTest.java
tests/robotests/src/com/android/settings/testutils/FakeSliderController.java [new file with mode: 0644]

diff --git a/src/com/android/settings/core/SliderPreferenceController.java b/src/com/android/settings/core/SliderPreferenceController.java
new file mode 100644 (file)
index 0000000..0baa868
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 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 com.android.settings.core;
+
+import android.content.Context;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.SeekBarPreference;
+
+import com.android.settings.slices.SliceData;
+
+public abstract class SliderPreferenceController extends BasePreferenceController implements
+        Preference.OnPreferenceChangeListener {
+
+    public SliderPreferenceController(Context context, String preferenceKey) {
+        super(context, preferenceKey);
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object newValue) {
+        return setSliderPosition((int) newValue);
+    }
+
+    @Override
+    public void updateState(Preference preference) {
+        ((SeekBarPreference) preference).setValue(getSliderPosition());
+    }
+
+    /**
+     * @return the value of the Slider's position based on the range: [0, maxSteps).
+     */
+    public abstract int getSliderPosition();
+
+    /**
+     * Set the slider to a new value.
+     *
+     * @param position of the slider.
+     * @return {@code true} if the position is successfully set.
+     */
+    public abstract boolean setSliderPosition(int position);
+
+    /**
+     * @return the number of steps supported by the slider.
+     */
+    public abstract int getMaxSteps();
+
+    @Override
+    public int getSliceType() {
+        return SliceData.SliceType.SLIDER;
+    }
+}
index cd4131d..779775b 100644 (file)
@@ -58,7 +58,7 @@ public abstract class TogglePreferenceController extends BasePreferenceControlle
 
     @Override
     public final boolean onPreferenceChange(Preference preference, Object newValue) {
-        return setChecked((Boolean) newValue);
+        return setChecked((boolean) newValue);
     }
 
     @Override
index ddda5d8..802f1e4 100644 (file)
@@ -74,9 +74,21 @@ public class SettingsSliceProvider extends SliceProvider {
     public static final String ACTION_WIFI_CHANGED =
             "com.android.settings.slice.action.WIFI_CHANGED";
 
+    /**
+     * Action passed for changes to Toggle Slices.
+     */
     public static final String ACTION_TOGGLE_CHANGED =
             "com.android.settings.slice.action.TOGGLE_CHANGED";
 
+    /**
+     * Action passed for changes to Slider Slices.
+     */
+    public static final String ACTION_SLIDER_CHANGED =
+            "com.android.settings.slice.action.SLIDER_CHANGED";
+
+    /**
+     * Intent Extra passed for the key identifying the Setting Slice.
+     */
     public static final String EXTRA_SLICE_KEY = "com.android.settings.slice.extra.key";
 
     // TODO -- Associate slice URI with search result instead of separate hardcoded thing
index 4124df7..c455640 100644 (file)
 
 package com.android.settings.slices;
 
+import static com.android.settings.slices.SettingsSliceProvider.ACTION_SLIDER_CHANGED;
 import static com.android.settings.slices.SettingsSliceProvider.ACTION_TOGGLE_CHANGED;
 import static com.android.settings.slices.SettingsSliceProvider.ACTION_WIFI_CHANGED;
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
 
-import android.app.slice.Slice;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -30,8 +30,13 @@ import android.os.Handler;
 import android.text.TextUtils;
 
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.SliderPreferenceController;
 import com.android.settings.core.TogglePreferenceController;
 
+import android.app.slice.Slice;
+
+import androidx.slice.core.SliceHints;
+
 /**
  * Responds to actions performed on slices and notifies slices of updates in state changes.
  */
@@ -51,6 +56,10 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
             case ACTION_TOGGLE_CHANGED:
                 handleToggleAction(context, key);
                 break;
+            case ACTION_SLIDER_CHANGED:
+                int newPosition = intent.getIntExtra(SliceHints.EXTRA_RANGE_VALUE, -1);
+                handleSliderAction(context, key, newPosition);
+                break;
             case ACTION_WIFI_CHANGED:
                 WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                 boolean newState = intent.getBooleanExtra(Slice.EXTRA_TOGGLE_STATE,
@@ -85,6 +94,33 @@ public class SliceBroadcastReceiver extends BroadcastReceiver {
         toggleController.setChecked(!currentValue);
     }
 
+    private void handleSliderAction(Context context, String key, int newPosition) {
+        if (TextUtils.isEmpty(key)) {
+            throw new IllegalArgumentException(
+                    "No key passed to Intent for slider controller. Use extra: " + EXTRA_SLICE_KEY);
+        }
+
+        if (newPosition == -1) {
+            throw new IllegalArgumentException("Invalid position passed to Slider controller");
+        }
+
+        final BasePreferenceController controller = getPreferenceController(context, key);
+
+        if (!(controller instanceof SliderPreferenceController)) {
+            throw new IllegalArgumentException("Slider action passed for a non-slider key: " + key);
+        }
+
+        final SliderPreferenceController sliderController = (SliderPreferenceController) controller;
+        final int maxSteps = sliderController.getMaxSteps();
+        if (newPosition < 0 || newPosition > maxSteps) {
+            throw new IllegalArgumentException(
+                    "Invalid position passed to Slider controller. Expected between 0 and "
+                            + maxSteps + " but found " + newPosition);
+        }
+
+        sliderController.setSliderPosition(newPosition);
+    }
+
     private BasePreferenceController getPreferenceController(Context context, String key) {
         final SlicesDatabaseAccessor accessor = new SlicesDatabaseAccessor(context);
         final SliceData sliceData = accessor.getSliceDataFromKey(key);
index 49972a8..43cba73 100644 (file)
@@ -18,6 +18,8 @@ package com.android.settings.slices;
 
 import static com.android.settings.slices.SettingsSliceProvider.EXTRA_SLICE_KEY;
 
+import static androidx.slice.builders.ListBuilder.ICON_IMAGE;
+
 import android.app.PendingIntent;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -32,6 +34,7 @@ import com.android.internal.annotations.VisibleForTesting;
 import com.android.settings.R;
 import com.android.settings.SubSettings;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.SliderPreferenceController;
 import com.android.settings.core.TogglePreferenceController;
 import com.android.settings.search.DatabaseIndexingUtils;
 import com.android.settingslib.core.AbstractPreferenceController;
@@ -41,6 +44,7 @@ import androidx.slice.builders.SliceAction;
 import androidx.slice.builders.ListBuilder;
 import androidx.slice.builders.ListBuilder.RowBuilder;
 
+
 /**
  * Utility class to build Slices objects and Preference Controllers based on the Database managed
  * by {@link SlicesDatabaseHelper}
@@ -57,28 +61,19 @@ public class SliceBuilderUtils {
      * {@param sliceData} is an inline controller.
      */
     public static Slice buildSlice(Context context, SliceData sliceData) {
-        final PendingIntent contentIntent = getContentIntent(context, sliceData);
-        final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
-        final BasePreferenceController controller = getPreferenceController(context, sliceData);
-
-        final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
-
-        final RowBuilder builder = new RowBuilder(context, sliceData.getUri())
-                .setTitle(sliceData.getTitle())
-                .setTitleItem(icon)
-                .setSubtitle(subtitleText)
-                .setPrimaryAction(new SliceAction(contentIntent, null, null));
-
         // TODO (b/71640747) Respect setting availability.
-
-        if (sliceData.getSliceType() == SliceData.SliceType.SWITCH) {
-            addToggleAction(context, builder, ((TogglePreferenceController) controller).isChecked(),
-                    sliceData.getKey());
+        final BasePreferenceController controller = getPreferenceController(context, sliceData);
+        switch (sliceData.getSliceType()) {
+            case SliceData.SliceType.INTENT:
+                return buildIntentSlice(context, sliceData, controller);
+            case SliceData.SliceType.SWITCH:
+                return buildToggleSlice(context, sliceData, controller);
+            case SliceData.SliceType.SLIDER:
+                return buildSliderSlice(context, sliceData, controller);
+            default:
+                throw new IllegalArgumentException(
+                        "Slice type passed was invalid: " + sliceData.getSliceType());
         }
-
-        return new ListBuilder(context, sliceData.getUri())
-                .addRow(builder)
-                .build();
     }
 
     /**
@@ -145,6 +140,55 @@ public class SliceBuilderUtils {
                 .build();
     }
 
+    private static Slice buildToggleSlice(Context context, SliceData sliceData,
+            BasePreferenceController controller) {
+        final PendingIntent contentIntent = getContentIntent(context, sliceData);
+        final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
+        final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
+        final TogglePreferenceController toggleController =
+                (TogglePreferenceController) controller;
+        final SliceAction sliceAction = getToggleAction(context, sliceData.getKey(),
+                toggleController.isChecked());
+
+        return new ListBuilder(context, sliceData.getUri())
+                .addRow(rowBuilder -> rowBuilder
+                        .setTitle(sliceData.getTitle())
+                        .setTitleItem(icon, ICON_IMAGE)
+                        .setSubtitle(subtitleText)
+                        .setPrimaryAction(new SliceAction(contentIntent, null, null))
+                        .addEndItem(sliceAction))
+                .build();
+    }
+
+    private static Slice buildIntentSlice(Context context, SliceData sliceData,
+            BasePreferenceController controller) {
+        final PendingIntent contentIntent = getContentIntent(context, sliceData);
+        final Icon icon = Icon.createWithResource(context, sliceData.getIconResource());
+        final CharSequence subtitleText = getSubtitleText(context, controller, sliceData);
+
+        return new ListBuilder(context, sliceData.getUri())
+                .addRow(rowBuilder -> rowBuilder
+                        .setTitle(sliceData.getTitle())
+                        .setTitleItem(icon, ICON_IMAGE)
+                        .setSubtitle(subtitleText)
+                        .setPrimaryAction(new SliceAction(contentIntent, null, null)))
+                .build();
+    }
+
+    private static Slice buildSliderSlice(Context context, SliceData sliceData,
+            BasePreferenceController controller) {
+        final SliderPreferenceController sliderController =
+                (SliderPreferenceController) controller;
+        final PendingIntent actionIntent = getSliderAction(context, sliceData.getKey());
+        return new ListBuilder(context, sliceData.getUri())
+                .addInputRange(builder -> builder
+                        .setTitle(sliceData.getTitle())
+                        .setMax(sliderController.getMaxSteps())
+                        .setValue(sliderController.getSliderPosition())
+                        .setAction(actionIntent))
+                .build();
+    }
+
     private static BasePreferenceController getPreferenceController(Context context,
             String controllerClassName, String controllerKey) {
         try {
@@ -156,11 +200,14 @@ public class SliceBuilderUtils {
         return BasePreferenceController.createInstance(context, controllerClassName, controllerKey);
     }
 
-    private static void addToggleAction(Context context, RowBuilder builder, boolean isChecked,
-            String key) {
+    private static SliceAction getToggleAction(Context context, String key, boolean isChecked) {
         PendingIntent actionIntent = getActionIntent(context,
                 SettingsSliceProvider.ACTION_TOGGLE_CHANGED, key);
-        builder.addEndItem(new SliceAction(actionIntent, null, isChecked));
+        return new SliceAction(actionIntent, null, isChecked);
+    }
+
+    private static PendingIntent getSliderAction(Context context, String key) {
+        return getActionIntent(context, SettingsSliceProvider.ACTION_SLIDER_CHANGED, key);
     }
 
     private static PendingIntent getActionIntent(Context context, String action, String key) {
diff --git a/tests/robotests/src/com/android/settings/core/SliderPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/core/SliderPreferenceControllerTest.java
new file mode 100644 (file)
index 0000000..f9f656e
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2018 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 com.android.settings.core;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.support.v7.preference.SeekBarPreference;
+
+import com.android.settings.slices.SliceData;
+import com.android.settings.testutils.SettingsRobolectricTestRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(SettingsRobolectricTestRunner.class)
+public class SliderPreferenceControllerTest {
+
+    FakeSlider mSliderController;
+
+    Context mContext;
+    SeekBarPreference mPreference;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mPreference = new SeekBarPreference(mContext);
+        mSliderController = new FakeSlider(mContext, "key");
+    }
+
+    @Test
+    public void onPreferenceChange_updatesPosition() {
+        final int newValue = 28;
+
+        mSliderController.onPreferenceChange(mPreference, newValue);
+
+        assertThat(mSliderController.getSliderPosition()).isEqualTo(newValue);
+    }
+
+    @Test
+    public void updateState_setsPreferenceToCurrentValue() {
+        final int newValue = 28;
+        mSliderController.setSliderPosition(newValue);
+
+        mSliderController.updateState(mPreference);
+
+        assertThat(mPreference.getValue()).isEqualTo(newValue);
+    }
+
+    @Test
+    public void testSliceType_returnsSliceType() {
+        assertThat(mSliderController.getSliceType()).isEqualTo(
+                SliceData.SliceType.SLIDER);
+    }
+
+    private class FakeSlider extends SliderPreferenceController {
+
+        private final int MAX_STEPS = 2112;
+        private int mPosition;
+
+        public FakeSlider(Context context, String key) {
+            super(context, key);
+        }
+
+        @Override
+        public int getSliderPosition() {
+            return mPosition;
+        }
+
+        @Override
+        public boolean setSliderPosition(int position) {
+            mPosition = position;
+            return true;
+        }
+
+        @Override
+        public int getMaxSteps() {
+            return MAX_STEPS;
+        }
+
+        @Override
+        public int getAvailabilityStatus() {
+            return AVAILABLE;
+        }
+    }
+}
index 965bec3..525ecc7 100644 (file)
@@ -18,7 +18,6 @@
 package com.android.settings.slices;
 
 import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.mock;
 
 import android.content.ContentValues;
 import android.content.Context;
@@ -28,7 +27,9 @@ import android.database.sqlite.SQLiteDatabase;
 import com.android.settings.search.FakeIndexProvider;
 import com.android.settings.search.SearchFeatureProvider;
 import com.android.settings.search.SearchFeatureProviderImpl;
+import com.android.settings.testutils.DatabaseTestUtils;
 import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.FakeSliderController;
 import com.android.settings.testutils.FakeToggleController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
@@ -38,6 +39,8 @@ import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.robolectric.RuntimeEnvironment;
 
+import androidx.slice.core.SliceHints;
+
 @RunWith(SettingsRobolectricTestRunner.class)
 public class SliceBroadcastReceiverTest {
 
@@ -46,7 +49,7 @@ public class SliceBroadcastReceiverTest {
     private final String fakeScreenTitle = "screen_title";
     private final int fakeIcon = 1234;
     private final String fakeFragmentClassName = FakeIndexProvider.class.getName();
-    private final String fakeControllerName = FakeToggleController.class.getName();
+    private final Class fakeControllerName = FakeToggleController.class;
 
     private Context mContext;
     private SQLiteDatabase mDb;
@@ -68,7 +71,7 @@ public class SliceBroadcastReceiverTest {
 
     @After
     public void cleanUp() {
-        mFakeFeatureFactory.searchFeatureProvider = mock(SearchFeatureProvider.class);
+        DatabaseTestUtils.clearDb(mContext);
     }
 
     @Test
@@ -90,20 +93,74 @@ public class SliceBroadcastReceiverTest {
         assertThat(fakeToggleController.isChecked()).isFalse();
     }
 
+    @Test
+    public void testOnReceive_sliderChanged() {
+        String key = "key";
+        final int position = FakeSliderController.MAX_STEPS - 1;
+        final int oldPosition = FakeSliderController.MAX_STEPS;
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        insertSpecialCase(FakeSliderController.class, key);
+
+        // Set slider setting
+        FakeSliderController fakeSliderController = new FakeSliderController(mContext, key);
+        fakeSliderController.setSliderPosition(oldPosition);
+        // Build action
+        Intent intent = new Intent(SettingsSliceProvider.ACTION_SLIDER_CHANGED);
+        intent.putExtra(SliceHints.EXTRA_RANGE_VALUE, position);
+        intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+        assertThat(fakeSliderController.getSliderPosition()).isEqualTo(oldPosition);
+
+        // Update the setting.
+        mReceiver.onReceive(mContext, intent);
+
+        assertThat(fakeSliderController.getSliderPosition()).isEqualTo(position);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testOnReceive_invalidController_throwsException() {
+        String key = "key";
+        final int position = 0;
+        mSearchFeatureProvider.getSearchIndexableResources().getProviderValues().clear();
+        insertSpecialCase(FakeToggleController.class, key);
+
+        // Build action
+        Intent intent = new Intent(SettingsSliceProvider.ACTION_SLIDER_CHANGED);
+        intent.putExtra(SliceHints.EXTRA_RANGE_VALUE, position);
+        intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, key);
+
+        // Trigger the exception.
+        mReceiver.onReceive(mContext, intent);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void sliderOnReceive_noKey_throwsException() {
+        // Build action
+        Intent intent = new Intent(SettingsSliceProvider.ACTION_SLIDER_CHANGED);
+        intent.putExtra(SliceHints.EXTRA_RANGE_VALUE, 0);
+
+        // Trigger the exception.
+        mReceiver.onReceive(mContext, intent);
+    }
+
     @Test(expected =  IllegalStateException.class)
-    public void testOnReceive_noExtra_illegalSatetException() {
+    public void toggleOnReceive_noExtra_illegalStateException() {
         Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
         mReceiver.onReceive(mContext, intent);
     }
 
     @Test(expected =  IllegalStateException.class)
-    public void testOnReceive_emptyKey_throwsIllegalStateException() {
+    public void toggleOnReceive_emptyKey_throwsIllegalStateException() {
         Intent intent = new Intent(SettingsSliceProvider.ACTION_TOGGLE_CHANGED);
         intent.putExtra(SettingsSliceProvider.EXTRA_SLICE_KEY, (String) null);
         mReceiver.onReceive(mContext, intent);
     }
 
     private void insertSpecialCase(String key) {
+        insertSpecialCase(fakeControllerName, key);
+    }
+
+    private void insertSpecialCase(Class controllerClass, String key) {
         ContentValues values = new ContentValues();
         values.put(SlicesDatabaseHelper.IndexColumns.KEY, key);
         values.put(SlicesDatabaseHelper.IndexColumns.TITLE, fakeTitle);
@@ -111,8 +168,7 @@ public class SliceBroadcastReceiverTest {
         values.put(SlicesDatabaseHelper.IndexColumns.SCREENTITLE, fakeScreenTitle);
         values.put(SlicesDatabaseHelper.IndexColumns.ICON_RESOURCE, fakeIcon);
         values.put(SlicesDatabaseHelper.IndexColumns.FRAGMENT, fakeFragmentClassName);
-        values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, fakeControllerName);
-
+        values.put(SlicesDatabaseHelper.IndexColumns.CONTROLLER, controllerClass.getName());
         mDb.replaceOrThrow(SlicesDatabaseHelper.Tables.TABLE_SLICES_INDEX, null, values);
     }
 }
\ No newline at end of file
index 869ba48..d0c0326 100644 (file)
@@ -28,6 +28,7 @@ import android.util.Pair;
 
 import com.android.settings.R;
 import com.android.settings.core.BasePreferenceController;
+import com.android.settings.testutils.FakeSliderController;
 import com.android.settings.testutils.FakeToggleController;
 import com.android.settings.testutils.SettingsRobolectricTestRunner;
 
@@ -69,6 +70,14 @@ public class SliceBuilderUtilsTest {
     }
 
     @Test
+    public void testSliderSlice_returnsSeekBarSlice() {
+        final Slice slice = SliceBuilderUtils.buildSlice(mContext, getDummyData(
+                FakeSliderController.class));
+
+        assertThat(slice).isNotNull();
+    }
+
+    @Test
     public void testUriBuilder_oemAuthority_intentPath_returnsValidSliceUri() {
         Uri expectedUri = new Uri.Builder()
                 .scheme(ContentResolver.SCHEME_CONTENT)
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java b/tests/robotests/src/com/android/settings/testutils/FakeSliderController.java
new file mode 100644 (file)
index 0000000..f4f91ed
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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 com.android.settings.testutils;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.SliderPreferenceController;
+
+public class FakeSliderController extends SliderPreferenceController {
+
+    private final String settingKey = "fake_slider_key";
+
+    public static final int MAX_STEPS = 9;
+
+    public FakeSliderController(Context context, String key) {
+        super(context, key);
+    }
+
+    @Override
+    public int getSliderPosition() {
+        return Settings.System.getInt(mContext.getContentResolver(), settingKey, 0);
+    }
+
+    @Override
+    public boolean setSliderPosition(int position) {
+        return Settings.System.putInt(mContext.getContentResolver(), settingKey, position);
+    }
+
+    @Override
+    public int getMaxSteps() {
+        return MAX_STEPS;
+    }
+
+    @Override
+    public int getAvailabilityStatus() {
+        return BasePreferenceController.AVAILABLE;
+    }
+}