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