Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad6678f9 authored by Matthew Fritze's avatar Matthew Fritze
Browse files

Add Slider template for Slices

Add the Seekbar preference equivalent
to the TwoStatePreference (toggle) preference
controller abstract controller.

Change-Id: I6ff91f2f72a7f72c18ddbc27b2b1fda4b6ce6ca9
Fixes: 67996707
Test: Robotests
parent 940630ba
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+1 −1
Original line number Diff line number Diff line
@@ -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
+12 −0
Original line number Diff line number Diff line
@@ -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
+37 −1
Original line number Diff line number Diff line
@@ -16,11 +16,11 @@

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);
+70 −23
Original line number Diff line number Diff line
@@ -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) {
Loading