Export callback to receive seekbar change event from SeekBarPrefernce
- Export onSeekBarChangeListener callback to receive change event from parent - Update battery saver schedule trigger threshold after seekbar tounch ending instead of update it every time during dragging or touching Bug: 236356020 Test: make RunSettingsRoboTests Change-Id: Ifee7cd9e7cabfbec0817a4c28254228f885d6a8d
This commit is contained in:
@@ -20,6 +20,8 @@ import android.content.Context;
|
|||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.Settings.Global;
|
import android.provider.Settings.Global;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.Preference.OnPreferenceChangeListener;
|
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.
|
* See {@link Settings.Global#AUTOMATIC_POWER_SAVE_MODE} for more details.
|
||||||
*/
|
*/
|
||||||
public class BatterySaverScheduleSeekBarController implements
|
public class BatterySaverScheduleSeekBarController implements
|
||||||
OnPreferenceChangeListener {
|
OnPreferenceChangeListener, OnSeekBarChangeListener {
|
||||||
|
|
||||||
public static final int MAX_SEEKBAR_VALUE = 15;
|
public static final int MAX_SEEKBAR_VALUE = 15;
|
||||||
public static final int MIN_SEEKBAR_VALUE = 2;
|
public static final int MIN_SEEKBAR_VALUE = 2;
|
||||||
public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
|
public static final String KEY_BATTERY_SAVER_SEEK_BAR = "battery_saver_seek_bar";
|
||||||
|
private static final int LEVEL_UNIT_SCALE = 5;
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public SeekBarPreference mSeekBarPreference;
|
public SeekBarPreference mSeekBarPreference;
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
int mPercentage;
|
||||||
|
|
||||||
public BatterySaverScheduleSeekBarController(Context context) {
|
public BatterySaverScheduleSeekBarController(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mSeekBarPreference = new SeekBarPreference(context);
|
mSeekBarPreference = new SeekBarPreference(context);
|
||||||
mSeekBarPreference.setLayoutResource(R.layout.preference_widget_seekbar_settings);
|
mSeekBarPreference.setLayoutResource(R.layout.preference_widget_seekbar_settings);
|
||||||
mSeekBarPreference.setIconSpaceReserved(false);
|
mSeekBarPreference.setIconSpaceReserved(false);
|
||||||
mSeekBarPreference.setOnPreferenceChangeListener(this);
|
mSeekBarPreference.setOnPreferenceChangeListener(this);
|
||||||
|
mSeekBarPreference.setOnSeekBarChangeListener(this);
|
||||||
mSeekBarPreference.setContinuousUpdates(true);
|
mSeekBarPreference.setContinuousUpdates(true);
|
||||||
mSeekBarPreference.setMax(MAX_SEEKBAR_VALUE);
|
mSeekBarPreference.setMax(MAX_SEEKBAR_VALUE);
|
||||||
mSeekBarPreference.setMin(MIN_SEEKBAR_VALUE);
|
mSeekBarPreference.setMin(MIN_SEEKBAR_VALUE);
|
||||||
@@ -68,16 +75,28 @@ public class BatterySaverScheduleSeekBarController implements
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||||
// The nits are in intervals of 5%
|
mPercentage = ((Integer) newValue) * LEVEL_UNIT_SCALE;
|
||||||
final int percentage = ((Integer) newValue) * 5;
|
final CharSequence stateDescription = formatStateDescription(mPercentage);
|
||||||
Settings.Global.putInt(mContext.getContentResolver(), Global.LOW_POWER_MODE_TRIGGER_LEVEL,
|
|
||||||
percentage);
|
|
||||||
final CharSequence stateDescription = formatStateDescription(percentage);
|
|
||||||
preference.setTitle(stateDescription);
|
preference.setTitle(stateDescription);
|
||||||
mSeekBarPreference.overrideSeekBarStateDescription(stateDescription);
|
mSeekBarPreference.overrideSeekBarStateDescription(stateDescription);
|
||||||
return true;
|
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() {
|
public void updateSeekBar() {
|
||||||
final ContentResolver resolver = mContext.getContentResolver();
|
final ContentResolver resolver = mContext.getContentResolver();
|
||||||
// Note: this can also be obtained via PowerManager.getPowerSaveModeTrigger()
|
// Note: this can also be obtained via PowerManager.getPowerSaveModeTrigger()
|
||||||
|
@@ -64,6 +64,7 @@ public class SeekBarPreference extends RestrictedPreference
|
|||||||
private CharSequence mOverrideSeekBarStateDescription;
|
private CharSequence mOverrideSeekBarStateDescription;
|
||||||
private CharSequence mSeekBarContentDescription;
|
private CharSequence mSeekBarContentDescription;
|
||||||
private CharSequence mSeekBarStateDescription;
|
private CharSequence mSeekBarStateDescription;
|
||||||
|
private OnSeekBarChangeListener mOnSeekBarChangeListener;
|
||||||
|
|
||||||
public SeekBarPreference(
|
public SeekBarPreference(
|
||||||
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||||
@@ -101,6 +102,14 @@ public class SeekBarPreference extends RestrictedPreference
|
|||||||
this(context, null);
|
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) {
|
public void setShouldBlink(boolean shouldBlink) {
|
||||||
mShouldBlink = shouldBlink;
|
mShouldBlink = shouldBlink;
|
||||||
notifyChanged();
|
notifyChanged();
|
||||||
@@ -301,6 +310,9 @@ public class SeekBarPreference extends RestrictedPreference
|
|||||||
if (fromUser && (mContinuousUpdates || !mTrackingTouch)) {
|
if (fromUser && (mContinuousUpdates || !mTrackingTouch)) {
|
||||||
syncProgress(seekBar);
|
syncProgress(seekBar);
|
||||||
}
|
}
|
||||||
|
if (mOnSeekBarChangeListener != null) {
|
||||||
|
mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -309,6 +321,9 @@ public class SeekBarPreference extends RestrictedPreference
|
|||||||
mJankMonitor.begin(InteractionJankMonitor.Configuration.Builder
|
mJankMonitor.begin(InteractionJankMonitor.Configuration.Builder
|
||||||
.withView(CUJ_SETTINGS_SLIDER, seekBar)
|
.withView(CUJ_SETTINGS_SLIDER, seekBar)
|
||||||
.setTag(getKey()));
|
.setTag(getKey()));
|
||||||
|
if (mOnSeekBarChangeListener != null) {
|
||||||
|
mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -317,6 +332,9 @@ public class SeekBarPreference extends RestrictedPreference
|
|||||||
if (seekBar.getProgress() != mProgress) {
|
if (seekBar.getProgress() != mProgress) {
|
||||||
syncProgress(seekBar);
|
syncProgress(seekBar);
|
||||||
}
|
}
|
||||||
|
if (mOnSeekBarChangeListener != null) {
|
||||||
|
mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
|
||||||
|
}
|
||||||
mJankMonitor.end(CUJ_SETTINGS_SLIDER);
|
mJankMonitor.end(CUJ_SETTINGS_SLIDER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,6 +12,7 @@ import android.content.Context;
|
|||||||
import android.os.PowerManager;
|
import android.os.PowerManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.provider.Settings.Global;
|
import android.provider.Settings.Global;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
@@ -46,22 +47,47 @@ public class BatterySaverScheduleSeekBarControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onPreferenceChange_updatesSettingsGlobal() {
|
public void onPreferenceChange_withoutOnStopTrackingTouch_updatesTitleAndDescriptionOnly() {
|
||||||
final CharSequence expectedTitle = "50%";
|
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);
|
|
||||||
|
|
||||||
|
mController.onPreferenceChange(mController.mSeekBarPreference, 10);
|
||||||
|
|
||||||
|
assertThat(getTriggerLevel()).isEqualTo(5);
|
||||||
assertThat(mController.mSeekBarPreference.getTitle()).isEqualTo(expectedTitle);
|
assertThat(mController.mSeekBarPreference.getTitle()).isEqualTo(expectedTitle);
|
||||||
verify(mController.mSeekBarPreference).overrideSeekBarStateDescription(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
|
@Test
|
||||||
public void updateSeekBar_routineMode_hasCorrectProperties() {
|
public void updateSeekBar_routineMode_hasCorrectProperties() {
|
||||||
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
||||||
PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
|
PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
|
||||||
|
|
||||||
mController.updateSeekBar();
|
mController.updateSeekBar();
|
||||||
|
|
||||||
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
|
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
|
||||||
verify(mController.mSeekBarPreference, never()).overrideSeekBarStateDescription(any());
|
verify(mController.mSeekBarPreference, never()).overrideSeekBarStateDescription(any());
|
||||||
}
|
}
|
||||||
@@ -71,7 +97,8 @@ public class BatterySaverScheduleSeekBarControllerTest {
|
|||||||
final CharSequence expectedTitle = "10%";
|
final CharSequence expectedTitle = "10%";
|
||||||
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
||||||
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
|
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
|
||||||
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 10);
|
setTriggerLevel(10);
|
||||||
|
|
||||||
mController.updateSeekBar();
|
mController.updateSeekBar();
|
||||||
|
|
||||||
assertThat(mController.mSeekBarPreference.isVisible()).isTrue();
|
assertThat(mController.mSeekBarPreference.isVisible()).isTrue();
|
||||||
@@ -83,8 +110,10 @@ public class BatterySaverScheduleSeekBarControllerTest {
|
|||||||
public void updateSeekBar_noneMode_hasCorrectProperties() {
|
public void updateSeekBar_noneMode_hasCorrectProperties() {
|
||||||
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
||||||
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
|
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
|
||||||
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
|
setTriggerLevel(0);
|
||||||
|
|
||||||
mController.updateSeekBar();
|
mController.updateSeekBar();
|
||||||
|
|
||||||
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
|
assertThat(mController.mSeekBarPreference.isVisible()).isFalse();
|
||||||
verify(mController.mSeekBarPreference, never()).overrideSeekBarStateDescription(any());
|
verify(mController.mSeekBarPreference, never()).overrideSeekBarStateDescription(any());
|
||||||
}
|
}
|
||||||
@@ -93,9 +122,18 @@ public class BatterySaverScheduleSeekBarControllerTest {
|
|||||||
public void addToScreen_addsToEnd() {
|
public void addToScreen_addsToEnd() {
|
||||||
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
Settings.Global.putInt(mResolver, Global.AUTOMATIC_POWER_SAVE_MODE,
|
||||||
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
|
PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
|
||||||
Settings.Global.putInt(mResolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 15);
|
setTriggerLevel(15);
|
||||||
|
|
||||||
mController.addToScreen(mScreen);
|
mController.addToScreen(mScreen);
|
||||||
|
|
||||||
assertThat(mController.mSeekBarPreference.getOrder()).isEqualTo(100);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@ import static com.google.common.truth.Truth.assertThat;
|
|||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
import static org.robolectric.Shadows.shadowOf;
|
import static org.robolectric.Shadows.shadowOf;
|
||||||
|
|
||||||
@@ -40,6 +41,7 @@ import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
import org.robolectric.RuntimeEnvironment;
|
import org.robolectric.RuntimeEnvironment;
|
||||||
@@ -59,6 +61,9 @@ public class SeekBarPreferenceTest {
|
|||||||
private SeekBarPreference mSeekBarPreference;
|
private SeekBarPreference mSeekBarPreference;
|
||||||
private SeekBar mSeekBar;
|
private SeekBar mSeekBar;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
SeekBar.OnSeekBarChangeListener mMockOnSeekBarChangeListener;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
@@ -179,6 +184,54 @@ public class SeekBarPreferenceTest {
|
|||||||
assertThat(shadowOf(mSeekBar).lastHapticFeedbackPerformed()).isEqualTo(CLOCK_TICK);
|
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 {
|
public static class TestFragment extends PreferenceFragmentCompat {
|
||||||
@Override
|
@Override
|
||||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||||
|
Reference in New Issue
Block a user