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

Commit 60ecf13e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Export callback to receive seekbar change event from SeekBarPrefernce"

parents a7e2ec53 d3bead82
Loading
Loading
Loading
Loading
+25 −6
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
@@ -42,22 +44,27 @@ import com.android.settings.widget.SeekBarPreference;
 * See {@link Settings.Global#AUTOMATIC_POWER_SAVE_MODE} for more details.
 */
public class BatterySaverScheduleSeekBarController implements
        OnPreferenceChangeListener {
        OnPreferenceChangeListener, OnSeekBarChangeListener {

    public static final int MAX_SEEKBAR_VALUE = 15;
    public static final int MIN_SEEKBAR_VALUE = 2;
    public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
    private static final int LEVEL_UNIT_SCALE = 5;

    @VisibleForTesting
    public SeekBarPreference mSeekBarPreference;
    private Context mContext;

    @VisibleForTesting
    int mPercentage;

    public BatterySaverScheduleSeekBarController(Context context) {
        mContext = context;
        mSeekBarPreference = new SeekBarPreference(context);
        mSeekBarPreference.setLayoutResource(R.layout.preference_widget_seekbar_settings);
        mSeekBarPreference.setIconSpaceReserved(false);
        mSeekBarPreference.setOnPreferenceChangeListener(this);
        mSeekBarPreference.setOnSeekBarChangeListener(this);
        mSeekBarPreference.setContinuousUpdates(true);
        mSeekBarPreference.setMax(MAX_SEEKBAR_VALUE);
        mSeekBarPreference.setMin(MIN_SEEKBAR_VALUE);
@@ -68,16 +75,28 @@ public class BatterySaverScheduleSeekBarController implements

    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
        // The nits are in intervals of 5%
        final int percentage = ((Integer) newValue) * 5;
        Settings.Global.putInt(mContext.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL,
                percentage);
        final CharSequence stateDescription = formatStateDescription(percentage);
        mPercentage = ((Integer) newValue) * LEVEL_UNIT_SCALE;
        final CharSequence stateDescription = formatStateDescription(mPercentage);
        preference.setTitle(stateDescription);
        mSeekBarPreference.overrideSeekBarStateDescription(stateDescription);
        return true;
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {}

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {}

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        if (mPercentage > 0) {
            Settings.Global.putInt(mContext.getContentResolver(),
                    Global.LOW_POWER_MODE_TRIGGER_LEVEL,
                    mPercentage);
        }
    }

    public void updateSeekBar() {
        final ContentResolver resolver = mContext.getContentResolver();
        // Note: this can also be obtained via PowerManager.getPowerSaveModeTrigger()
+18 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ public class SeekBarPreference extends RestrictedPreference
    private CharSequence mOverrideSeekBarStateDescription;
    private CharSequence mSeekBarContentDescription;
    private CharSequence mSeekBarStateDescription;
    private OnSeekBarChangeListener mOnSeekBarChangeListener;

    public SeekBarPreference(
            Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
@@ -101,6 +102,14 @@ public class SeekBarPreference extends RestrictedPreference
        this(context, null);
    }

    /**
     * A callback that notifies clients when the seekbar progress level has been
     * changed. See {@link OnSeekBarChangeListener} for more info.
     */
    public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
        mOnSeekBarChangeListener = listener;
    }

    public void setShouldBlink(boolean shouldBlink) {
        mShouldBlink = shouldBlink;
        notifyChanged();
@@ -301,6 +310,9 @@ public class SeekBarPreference extends RestrictedPreference
        if (fromUser && (mContinuousUpdates || !mTrackingTouch)) {
            syncProgress(seekBar);
        }
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
        }
    }

    @Override
@@ -309,6 +321,9 @@ public class SeekBarPreference extends RestrictedPreference
        mJankMonitor.begin(InteractionJankMonitor.Configuration.Builder
                .withView(CUJ_SETTINGS_SLIDER, seekBar)
                .setTag(getKey()));
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
        }
    }

    @Override
@@ -317,6 +332,9 @@ public class SeekBarPreference extends RestrictedPreference
        if (seekBar.getProgress() != mProgress) {
            syncProgress(seekBar);
        }
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
        }
        mJankMonitor.end(CUJ_SETTINGS_SLIDER);
    }

+45 −7
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ import android.content.Context;
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.widget.SeekBar;

import androidx.preference.PreferenceScreen;

@@ -46,22 +47,47 @@ public class BatterySaverScheduleSeekBarControllerTest {
    }

    @Test
    public void onPreferenceChange_updatesSettingsGlobal() {
    public void onPreferenceChange_withoutOnStopTrackingTouch_updatesTitleAndDescriptionOnly() {
        final CharSequence expectedTitle = "50%";
        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
        setTriggerLevel(5);

        mController.onPreferenceChange(mController.mSeekBarPreference, 10);
        assertThat(Settings.Global.getInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1))
                .isEqualTo(50);

        assertThat(getTriggerLevel()).isEqualTo(5);
        assertThat(mController.mSeekBarPreference.getTitle()).isEqualTo(expectedTitle);
        verify(mController.mSeekBarPreference).overrideSeekBarStateDescription(expectedTitle);
    }

    @Test
    public void onPreferenceChange_withOnStopTrackingTouch_updatesSettingsGlobal() {
        final CharSequence expectedTitle = "50%";
        setTriggerLevel(5);

        mController.onPreferenceChange(mController.mSeekBarPreference, 10);
        mController.onStopTrackingTouch(new SeekBar(mContext));

        assertThat(getTriggerLevel()).isEqualTo(50);
        assertThat(mController.mSeekBarPreference.getTitle()).isEqualTo(expectedTitle);
        verify(mController.mSeekBarPreference).overrideSeekBarStateDescription(expectedTitle);
    }

    @Test
    public void onStopTrackingTouch_invalidValue_noUpdates() {
        setTriggerLevel(5);

        mController.mPercentage = 0;
        mController.onStopTrackingTouch(new SeekBar(mContext));

        assertThat(getTriggerLevel()).isEqualTo(5);
    }

    @Test
    public void updateSeekBar_routineMode_hasCorrectProperties() {
        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
                PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);

        mController.updateSeekBar();

        assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
        verify(mController.mSeekBarPreference, never()).overrideSeekBarStateDescription(any());
    }
@@ -71,7 +97,8 @@ public class BatterySaverScheduleSeekBarControllerTest {
        final CharSequence expectedTitle = "10%";
        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 10);
        setTriggerLevel(10);

        mController.updateSeekBar();

        assertThat(mController.mSeekBarPreference.isVisible()).isTrue();
@@ -83,8 +110,10 @@ public class BatterySaverScheduleSeekBarControllerTest {
    public void updateSeekBar_noneMode_hasCorrectProperties() {
        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
        setTriggerLevel(0);

        mController.updateSeekBar();

        assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
        verify(mController.mSeekBarPreference, never()).overrideSeekBarStateDescription(any());
    }
@@ -93,9 +122,18 @@ public class BatterySaverScheduleSeekBarControllerTest {
    public void addToScreen_addsToEnd() {
        Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
                PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
        setTriggerLevel(15);

        mController.addToScreen(mScreen);

        assertThat(mController.mSeekBarPreference.getOrder()).isEqualTo(100);
    }

    private void setTriggerLevel(int level) {
        Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, level);
    }

    private int getTriggerLevel() {
        return Settings.Global.getInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, -1);
    }
}
+53 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;

@@ -40,6 +41,7 @@ import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@@ -59,6 +61,9 @@ public class SeekBarPreferenceTest {
    private SeekBarPreference mSeekBarPreference;
    private SeekBar mSeekBar;

    @Mock
    SeekBar.OnSeekBarChangeListener mMockOnSeekBarChangeListener;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
@@ -179,6 +184,54 @@ public class SeekBarPreferenceTest {
        assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
    }

    @Test
    public void onProgressChanged_hasSeekBarChangeListener_receiveCallBack() {
        mSeekBarPreference.setOnSeekBarChangeListener(mMockOnSeekBarChangeListener);

        mSeekBarPreference.onProgressChanged(mSeekBar, PROGRESS, true);

        verify(mMockOnSeekBarChangeListener).onProgressChanged(mSeekBar, PROGRESS, true);
    }

    @Test
    public void onProgressChanged_noSeekBarChangeListener_noAction() {
        mSeekBarPreference.onProgressChanged(mSeekBar, PROGRESS, true);

        verifyZeroInteractions(mMockOnSeekBarChangeListener);
    }

    @Test
    public void onStartTrackingTouch_hasSeekBarChangeListener_receiveCallBack() {
        mSeekBarPreference.setOnSeekBarChangeListener(mMockOnSeekBarChangeListener);

        mSeekBarPreference.onStartTrackingTouch(mSeekBar);

        verify(mMockOnSeekBarChangeListener).onStartTrackingTouch(mSeekBar);
    }

    @Test
    public void onStartTrackingTouch_noSeekBarChangeListener_noAction() {
        mSeekBarPreference.onStartTrackingTouch(mSeekBar);

        verifyZeroInteractions(mMockOnSeekBarChangeListener);
    }

    @Test
    public void onStopTrackingTouch_hasSeekBarChangeListener_receiveCallBack() {
        mSeekBarPreference.setOnSeekBarChangeListener(mMockOnSeekBarChangeListener);

        mSeekBarPreference.onStopTrackingTouch(mSeekBar);

        verify(mMockOnSeekBarChangeListener).onStopTrackingTouch(mSeekBar);
    }

    @Test
    public void onStopTrackingTouch_noSeekBarChangeListener_noAction() {
        mSeekBarPreference.onStopTrackingTouch(mSeekBar);

        verifyZeroInteractions(mMockOnSeekBarChangeListener);
    }

    public static class TestFragment extends PreferenceFragmentCompat {
        @Override
        public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {