• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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