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.provider.Settings; 21 22 import androidx.preference.Preference; 23 import androidx.preference.PreferenceScreen; 24 25 import com.android.internal.annotations.VisibleForTesting; 26 import com.android.settings.R; 27 import com.android.settings.core.TogglePreferenceController; 28 29 import org.checkerframework.checker.nullness.qual.MonotonicNonNull; 30 31 /** 32 * Configures the behaviour of long press power button action. 33 */ 34 public class LongPressPowerButtonPreferenceController extends TogglePreferenceController { 35 36 private static final String POWER_BUTTON_LONG_PRESS_SETTING = 37 Settings.Global.POWER_BUTTON_LONG_PRESS; 38 private static final String KEY_CHORD_POWER_VOLUME_UP_SETTING = 39 Settings.Global.KEY_CHORD_POWER_VOLUME_UP; 40 41 private static final String FOOTER_HINT_KEY = "power_menu_power_volume_up_hint"; 42 private static final String ASSIST_SWITCH_KEY = "gesture_power_menu_long_press_for_assist"; 43 44 /** 45 * Values used for long press power button behaviour when Assist setting is enabled. 46 * 47 * {@link com.android.server.policy.PhoneWindowManager#LONG_PRESS_POWER_GLOBAL_ACTIONS} for 48 * source of the value. 49 */ 50 @VisibleForTesting 51 static final int LONG_PRESS_POWER_NO_ACTION = 0; 52 @VisibleForTesting 53 static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1; 54 @VisibleForTesting 55 static final int LONG_PRESS_POWER_ASSISTANT_VALUE = 5; // Settings.Secure.ASSISTANT 56 57 /** 58 * Values used for volume key chord behaviour when Assist setting is enabled. 59 * 60 * Values based on config_keyChordPowerVolumeUp in 61 * frameworks/base/core/res/res/values/config.xml 62 */ 63 @VisibleForTesting 64 static final int KEY_CHORD_POWER_VOLUME_UP_NO_ACTION = 0; 65 @VisibleForTesting 66 static final int KEY_CHORD_POWER_VOLUME_UP_MUTE_TOGGLE = 1; 67 @VisibleForTesting 68 static final int KEY_CHORD_POWER_VOLUME_UP_GLOBAL_ACTIONS = 2; 69 70 /** 71 * Value used for long press power button behaviour when the Assist setting is disabled. 72 * 73 * If this value matches Assist setting, then it falls back to Global Actions panel or 74 * power menu, depending on their respective settings. 75 */ 76 private static final int POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE = 77 com.android.internal.R.integer.config_longPressOnPowerBehavior; 78 79 private static final int KEY_CHORD_POWER_VOLUME_UP_DEFAULT_VALUE_RESOURCE = 80 com.android.internal.R.integer.config_keyChordPowerVolumeUp; 81 82 @MonotonicNonNull 83 @VisibleForTesting 84 Preference mFooterHint; 85 86 @MonotonicNonNull 87 @VisibleForTesting 88 Preference mAssistSwitch; 89 LongPressPowerButtonPreferenceController(Context context, String key)90 public LongPressPowerButtonPreferenceController(Context context, String key) { 91 super(context, key); 92 } 93 94 @Override displayPreference(PreferenceScreen screen)95 public void displayPreference(PreferenceScreen screen) { 96 super.displayPreference(screen); 97 mFooterHint = screen.findPreference(FOOTER_HINT_KEY); 98 mAssistSwitch = screen.findPreference(ASSIST_SWITCH_KEY); 99 refreshStateDisplay(); 100 } 101 102 @Override getSummary()103 public CharSequence getSummary() { 104 final int powerButtonValue = getPowerButtonValue(); 105 if (powerButtonValue == LONG_PRESS_POWER_ASSISTANT_VALUE) { 106 return mContext.getString(R.string.power_menu_summary_long_press_for_assist_enabled); 107 } else if (powerButtonValue == LONG_PRESS_POWER_GLOBAL_ACTIONS) { 108 return mContext.getString( 109 R.string.power_menu_summary_long_press_for_assist_disabled_with_power_menu); 110 } else { 111 return mContext.getString( 112 R.string.power_menu_summary_long_press_for_assist_disabled_no_action); 113 } 114 } 115 116 @Override getAvailabilityStatus()117 public int getAvailabilityStatus() { 118 final boolean enabled = mContext.getResources().getBoolean( 119 com.android.internal.R.bool.config_longPressOnPowerForAssistantSettingAvailable); 120 return enabled ? AVAILABLE : UNSUPPORTED_ON_DEVICE; 121 } 122 123 @Override isChecked()124 public boolean isChecked() { 125 return getPowerButtonValue() == LONG_PRESS_POWER_ASSISTANT_VALUE; 126 } 127 128 @Override setChecked(boolean isChecked)129 public boolean setChecked(boolean isChecked) { 130 if (setPowerLongPressValue(isChecked)) { 131 // The key chord value is dependant on the long press setting and it always 132 // toggled in tandem. POWER_BUTTON_LONG_PRESS_SETTING is always the source 133 // of truth for both. 134 setPowerVolumeChordValue(isChecked); 135 refreshStateDisplay(); 136 return true; 137 } 138 139 return false; 140 } 141 refreshStateDisplay()142 private void refreshStateDisplay() { 143 if (mAssistSwitch != null) { 144 mAssistSwitch.setSummary(getSummary()); 145 } 146 147 if (mFooterHint != null) { 148 String footerHintText = mContext.getString(R.string.power_menu_power_volume_up_hint); 149 // If the device supports hush gesture, we need to notify the user where to find 150 // the setting. 151 if (mContext.getResources().getBoolean( 152 com.android.internal.R.bool.config_volumeHushGestureEnabled)) { 153 footerHintText = footerHintText + "\n\n" + mContext.getString( 154 R.string.power_menu_power_prevent_ringing_hint); 155 } 156 157 mFooterHint.setSummary(footerHintText); 158 mFooterHint.setVisible(isPowerMenuKeyChordEnabled(mContext)); 159 } 160 } 161 getPowerButtonValue()162 private int getPowerButtonValue() { 163 return Settings.Global.getInt(mContext.getContentResolver(), 164 POWER_BUTTON_LONG_PRESS_SETTING, 165 mContext.getResources().getInteger(POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE)); 166 } 167 isPowerMenuKeyChordEnabled(Context context)168 private static boolean isPowerMenuKeyChordEnabled(Context context) { 169 return Settings.Global.getInt(context.getContentResolver(), 170 KEY_CHORD_POWER_VOLUME_UP_SETTING, 171 context.getResources().getInteger( 172 com.android.internal.R.integer.config_keyChordPowerVolumeUp)) 173 == KEY_CHORD_POWER_VOLUME_UP_GLOBAL_ACTIONS; 174 } 175 setPowerLongPressValue(boolean isChecked)176 private boolean setPowerLongPressValue(boolean isChecked) { 177 if (isChecked) { 178 return Settings.Global.putInt(mContext.getContentResolver(), 179 POWER_BUTTON_LONG_PRESS_SETTING, LONG_PRESS_POWER_ASSISTANT_VALUE); 180 } 181 182 // We need to determine the right disabled value - we set it to device default 183 // if it's different than Assist, otherwise we fallback to either global actions or power 184 // menu. 185 final int defaultPowerButtonValue = mContext.getResources().getInteger( 186 POWER_BUTTON_LONG_PRESS_DEFAULT_VALUE_RESOURCE); 187 if (defaultPowerButtonValue == LONG_PRESS_POWER_ASSISTANT_VALUE) { 188 return Settings.Global.putInt(mContext.getContentResolver(), 189 POWER_BUTTON_LONG_PRESS_SETTING, LONG_PRESS_POWER_NO_ACTION); 190 } 191 192 return Settings.Global.putInt(mContext.getContentResolver(), 193 POWER_BUTTON_LONG_PRESS_SETTING, defaultPowerButtonValue); 194 } 195 196 /** 197 * Updates {@link Settings.Global.KEY_CHORD_POWER_VOLUME_UP} based on the changed value of 198 * {@link #POWER_BUTTON_LONG_PRESS_SETTING}. If power button is used for Assist, key chord 199 * should show the power menu. 200 */ setPowerVolumeChordValue(boolean isPowerButtonLongPressChecked)201 private boolean setPowerVolumeChordValue(boolean isPowerButtonLongPressChecked) { 202 if (isPowerButtonLongPressChecked) { 203 return Settings.Global.putInt(mContext.getContentResolver(), 204 KEY_CHORD_POWER_VOLUME_UP_SETTING, KEY_CHORD_POWER_VOLUME_UP_GLOBAL_ACTIONS); 205 } 206 207 // We restore key chord to the default value. 208 int keyChordDefaultValue = mContext.getResources().getInteger( 209 KEY_CHORD_POWER_VOLUME_UP_DEFAULT_VALUE_RESOURCE); 210 return Settings.Global.putInt(mContext.getContentResolver(), 211 KEY_CHORD_POWER_VOLUME_UP_SETTING, keyChordDefaultValue); 212 } 213 214 } 215