1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.gestures; 18 19 import android.content.Context; 20 import android.database.ContentObserver; 21 import android.os.Handler; 22 import android.provider.Settings; 23 24 import androidx.annotation.Nullable; 25 import androidx.preference.Preference; 26 import androidx.preference.PreferenceScreen; 27 28 import com.android.settings.core.SliderPreferenceController; 29 import com.android.settings.widget.LabeledSeekBarPreference; 30 import com.android.settingslib.core.lifecycle.LifecycleObserver; 31 import com.android.settingslib.core.lifecycle.events.OnStart; 32 import com.android.settingslib.core.lifecycle.events.OnStop; 33 34 /** Handles changes to the long press power button sensitivity slider. */ 35 public class LongPressPowerSensitivityPreferenceController extends 36 SliderPreferenceController implements 37 LifecycleObserver, OnStart, OnStop { 38 39 private final ContentObserver mPowerButtonObserver = new ContentObserver(Handler.getMain()) { 40 @Override 41 public void onChange(boolean selfChange) { 42 if (mPreference != null) { 43 updateState(mPreference); 44 } 45 } 46 }; 47 48 @Nullable 49 private final int[] mSensitivityValues; 50 51 @Nullable 52 private LabeledSeekBarPreference mPreference; 53 LongPressPowerSensitivityPreferenceController(Context context, String preferenceKey)54 public LongPressPowerSensitivityPreferenceController(Context context, String preferenceKey) { 55 super(context, preferenceKey); 56 mSensitivityValues = context.getResources().getIntArray( 57 com.android.internal.R.array.config_longPressOnPowerDurationSettings); 58 } 59 60 @Override onStart()61 public void onStart() { 62 mContext.getContentResolver().registerContentObserver( 63 Settings.Global.getUriFor(PowerMenuSettingsUtils.POWER_BUTTON_LONG_PRESS_SETTING), 64 false, mPowerButtonObserver); 65 } 66 67 @Override onStop()68 public void onStop() { 69 mContext.getContentResolver().unregisterContentObserver(mPowerButtonObserver); 70 } 71 72 @Override displayPreference(PreferenceScreen screen)73 public void displayPreference(PreferenceScreen screen) { 74 super.displayPreference(screen); 75 mPreference = screen.findPreference(getPreferenceKey()); 76 if (mPreference != null) { 77 mPreference.setContinuousUpdates(false); 78 mPreference.setHapticFeedbackMode( 79 LabeledSeekBarPreference.HAPTIC_FEEDBACK_MODE_ON_TICKS); 80 mPreference.setMin(getMin()); 81 mPreference.setMax(getMax()); 82 } 83 } 84 85 @Override updateState(Preference preference)86 public void updateState(Preference preference) { 87 super.updateState(preference); 88 final LabeledSeekBarPreference pref = (LabeledSeekBarPreference) preference; 89 pref.setEnabled( 90 isAvailable() && PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)); 91 pref.setProgress(getSliderPosition()); 92 } 93 94 @Override getAvailabilityStatus()95 public int getAvailabilityStatus() { 96 if (mSensitivityValues == null || mSensitivityValues.length < 2) { 97 return UNSUPPORTED_ON_DEVICE; 98 } 99 100 if (!PowerMenuSettingsUtils.isLongPressPowerForAssistEnabled(mContext)) { 101 return DISABLED_DEPENDENT_SETTING; 102 } 103 104 return AVAILABLE; 105 } 106 107 @Override getSliderPosition()108 public int getSliderPosition() { 109 return mSensitivityValues == null ? 0 : closestValueIndex(mSensitivityValues, 110 getCurrentSensitivityValue()); 111 } 112 113 @Override setSliderPosition(int position)114 public boolean setSliderPosition(int position) { 115 if (mSensitivityValues == null || position < 0 || position >= mSensitivityValues.length) { 116 return false; 117 } 118 return Settings.Global.putInt(mContext.getContentResolver(), 119 Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, 120 mSensitivityValues[position]); 121 } 122 123 @Override getMax()124 public int getMax() { 125 if (mSensitivityValues == null || mSensitivityValues.length == 0) { 126 return 0; 127 } 128 return mSensitivityValues.length - 1; 129 } 130 131 @Override getMin()132 public int getMin() { 133 return 0; 134 } 135 getCurrentSensitivityValue()136 private int getCurrentSensitivityValue() { 137 return Settings.Global.getInt(mContext.getContentResolver(), 138 Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS, 139 mContext.getResources().getInteger( 140 com.android.internal.R.integer.config_longPressOnPowerDurationMs)); 141 } 142 closestValueIndex(int[] values, int needle)143 private static int closestValueIndex(int[] values, int needle) { 144 int minDistance = Integer.MAX_VALUE; 145 int valueIndex = 0; 146 for (int i = 0; i < values.length; i++) { 147 int diff = Math.abs(values[i] - needle); 148 if (diff < minDistance) { 149 minDistance = diff; 150 valueIndex = i; 151 } 152 } 153 return valueIndex; 154 } 155 } 156