diff options
12 files changed, 206 insertions, 9 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 87babc00ad89..86f02e418c3c 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -7762,6 +7762,21 @@ public final class Settings { public static final String BLUETOOTH_ON_WHILE_DRIVING = "bluetooth_on_while_driving"; /** + * What behavior should be invoked when the volume hush gesture is triggered + * One of VOLUME_HUSH_OFF, VOLUME_HUSH_VIBRATE, VOLUME_HUSH_MUTE. + * + * @hide + */ + public static final String VOLUME_HUSH_GESTURE = "volume_hush_gesture"; + + /** @hide */ public static final int VOLUME_HUSH_OFF = 0; + /** @hide */ public static final int VOLUME_HUSH_VIBRATE = 1; + /** @hide */ public static final int VOLUME_HUSH_MUTE = 2; + + private static final Validator VOLUME_HUSH_GESTURE_VALIDATOR = + NON_NEGATIVE_INTEGER_VALIDATOR; + + /** * The number of times (integer) the user has manually enabled battery saver. * @hide */ @@ -7875,6 +7890,7 @@ public final class Settings { SCREENSAVER_ACTIVATE_ON_SLEEP, LOCKDOWN_IN_POWER_MENU, SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, + VOLUME_HUSH_GESTURE }; /** @@ -8011,6 +8027,7 @@ public final class Settings { VALIDATORS.put(LOCKDOWN_IN_POWER_MENU, LOCKDOWN_IN_POWER_MENU_VALIDATOR); VALIDATORS.put(SHOW_FIRST_CRASH_DIALOG_DEV_OPTION, SHOW_FIRST_CRASH_DIALOG_DEV_OPTION_VALIDATOR); + VALIDATORS.put(VOLUME_HUSH_GESTURE, VOLUME_HUSH_GESTURE_VALIDATOR); VALIDATORS.put(ENABLED_NOTIFICATION_LISTENERS, ENABLED_NOTIFICATION_LISTENERS_VALIDATOR); //legacy restore setting VALIDATORS.put(ENABLED_NOTIFICATION_ASSISTANT, diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto index 4bb970799b18..953da1735fde 100644 --- a/core/proto/android/providers/settings.proto +++ b/core/proto/android/providers/settings.proto @@ -744,9 +744,10 @@ message SecureSettingsProto { optional SettingProto backup_manager_constants = 193; optional SettingProto backup_local_transport_parameters = 194; optional SettingProto bluetooth_on_while_driving = 195 [ (android.privacy).dest = DEST_AUTOMATIC ]; + optional SettingsProto volume_hush_gesture = 196 [ (android.privacy).dest = DEST_AUTOMATIC ]; // Please insert fields in the same order as in // frameworks/base/core/java/android/provider/Settings.java. - // Next tag = 196 + // Next tag = 197 } message SystemSettingsProto { diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index bbb0b0a778b7..55c17b9b2af4 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2911,6 +2911,10 @@ is non-interactive. --> <bool name="config_cameraDoubleTapPowerGestureEnabled">true</bool> + <!-- Allow the gesture power + volume up to change the ringer mode while the device + is interactive. --> + <bool name="config_volumeHushGestureEnabled">true</bool> + <!-- Name of the component to handle network policy notifications. If present, disables NetworkPolicyManagerService's presentation of data-usage notifications. --> <string translatable="false" name="config_networkPolicyNotificationComponent"></string> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index f0f7270253fd..ba85f700534b 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -4888,6 +4888,9 @@ <!-- Notification action for editing a screenshot (drawing on it, cropping it, etc) --> <string name="screenshot_edit">Edit</string> + <string name="volume_dialog_ringer_guidance_vibrate">Calls and notifications will vibrate</string> + <string name="volume_dialog_ringer_guidance_silent">Calls and notifications will be muted</string> + <!-- Title for the notification channel notifying user of settings system changes. [CHAR LIMIT=NONE] --> <string name="notification_channel_system_changes">System changes</string> <!-- Title for the notification channel notifying user of do not disturb system changes (i.e. Do Not Disturb has changed). [CHAR LIMIT=NONE] --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 4cf50f5f4f80..9d65a60b76d3 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -1024,6 +1024,8 @@ <java-symbol type="string" name="volume_icon_description_media" /> <java-symbol type="string" name="volume_icon_description_notification" /> <java-symbol type="string" name="volume_icon_description_ringer" /> + <java-symbol type="string" name="volume_dialog_ringer_guidance_vibrate" /> + <java-symbol type="string" name="volume_dialog_ringer_guidance_silent" /> <java-symbol type="string" name="wait" /> <java-symbol type="string" name="webpage_unresponsive" /> <java-symbol type="string" name="whichApplication" /> @@ -2621,6 +2623,7 @@ <java-symbol type="bool" name="config_cameraDoubleTapPowerGestureEnabled" /> <java-symbol type="integer" name="config_cameraLiftTriggerSensorType" /> <java-symbol type="string" name="config_cameraLiftTriggerSensorStringType" /> + <java-symbol type="bool" name="config_volumeHushGestureEnabled" /> <java-symbol type="drawable" name="platlogo_m" /> diff --git a/media/java/android/media/AudioManagerInternal.java b/media/java/android/media/AudioManagerInternal.java index 0a1de33b845b..98c2d7fdd55f 100644 --- a/media/java/android/media/AudioManagerInternal.java +++ b/media/java/android/media/AudioManagerInternal.java @@ -42,6 +42,8 @@ public abstract class AudioManagerInternal { public abstract void setRingerModeInternal(int ringerMode, String caller); + public abstract void silenceRingerModeInternal(String caller); + public abstract void updateRingerModeAffectedStreamsInternal(); public abstract void setAccessibilityServiceUids(IntArray uids); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java index 797b4f9fa9d5..3467df5df6fe 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java @@ -1928,6 +1928,9 @@ class SettingsProtoDumpUtil { dumpSetting(s, p, Settings.Secure.BLUETOOTH_ON_WHILE_DRIVING, SecureSettingsProto.BLUETOOTH_ON_WHILE_DRIVING); + dumpSetting(s, p, + Settings.Secure.VOLUME_HUSH_GESTURE, + SecureSettingsProto.VOLUME_HUSH_GESTURE); // Please insert new settings using the same order as in Settings.Secure. p.end(token); diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index b37071bf24cf..7fd06987e64a 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -2914,7 +2914,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 161; + private static final int SETTINGS_VERSION = 162; private final int mUserId; @@ -3673,6 +3673,21 @@ public class SettingsProvider extends ContentProvider { currentVersion = 161; } + if (currentVersion == 161) { + // Version 161: Add a gesture for silencing phones + final SettingsState secureSettings = getSecureSettingsLocked(userId); + final Setting currentSetting = secureSettings.getSettingLocked( + Secure.VOLUME_HUSH_GESTURE); + if (currentSetting.isNull()) { + secureSettings.insertSettingLocked( + Secure.VOLUME_HUSH_GESTURE, + Integer.toString(Secure.VOLUME_HUSH_VIBRATE), + null, true, SettingsState.SYSTEM_PACKAGE_NAME); + } + + currentVersion = 162; + } + // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 375c31a9ba09..a4b76080ed48 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -1353,8 +1353,6 @@ <string name="volume_dialog_title">%s volume controls</string> - <string name="volume_dialog_ringer_guidance_vibrate">Calls and notifications will vibrate</string> - <string name="volume_dialog_ringer_guidance_silent">Calls and notifications will be muted</string> <string name="volume_dialog_ringer_guidance_ring">Calls and notifications will ring</string> <string name="output_title">Media output</string> diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index e94d6bd5ee99..1c8a26cc61d1 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -451,11 +451,11 @@ public class VolumeDialogImpl implements VolumeDialog { toastText = R.string.volume_dialog_ringer_guidance_ring; break; case RINGER_MODE_SILENT: - toastText = R.string.volume_dialog_ringer_guidance_silent; + toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent; break; case RINGER_MODE_VIBRATE: default: - toastText = R.string.volume_dialog_ringer_guidance_vibrate; + toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate; } Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show(); diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index c036549ccb49..3a23f18b2f48 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -24,6 +24,9 @@ import static android.media.AudioManager.STREAM_ALARM; import static android.media.AudioManager.STREAM_MUSIC; import static android.media.AudioManager.STREAM_SYSTEM; import static android.os.Process.FIRST_APPLICATION_UID; +import static android.provider.Settings.Secure.VOLUME_HUSH_MUTE; +import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; +import static android.provider.Settings.Secure.VOLUME_HUSH_VIBRATE; import android.Manifest; import android.annotation.NonNull; @@ -108,6 +111,7 @@ import android.os.UserHandle; import android.os.UserManager; import android.os.UserManagerInternal; import android.os.UserManagerInternal.UserRestrictionsListener; +import android.os.VibrationEffect; import android.os.Vibrator; import android.provider.Settings; import android.provider.Settings.System; @@ -124,6 +128,7 @@ import android.util.Slog; import android.util.SparseIntArray; import android.view.KeyEvent; import android.view.accessibility.AccessibilityManager; +import android.widget.Toast; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.DumpUtils; @@ -440,6 +445,12 @@ public class AudioService extends IAudioService.Stub // Is there a vibrator private final boolean mHasVibrator; + // Used to play vibrations + private Vibrator mVibrator; + private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) + .build(); // Broadcast receiver for device connections intent broadcasts private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver(); @@ -697,8 +708,8 @@ public class AudioService extends IAudioService.Stub PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mAudioEventWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "handleAudioEvent"); - Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - mHasVibrator = vibrator == null ? false : vibrator.hasVibrator(); + mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); + mHasVibrator = mVibrator == null ? false : mVibrator.hasVibrator(); // Initialize volume int maxCallVolume = SystemProperties.getInt("ro.config.vc_call_vol_steps", -1); @@ -2423,6 +2434,54 @@ public class AudioService extends IAudioService.Stub setRingerMode(ringerMode, caller, false /*external*/); } + public void silenceRingerModeInternal(String reason) { + VibrationEffect effect = null; + int ringerMode = AudioManager.RINGER_MODE_SILENT; + int toastText = 0; + + int silenceRingerSetting = Settings.Secure.VOLUME_HUSH_OFF; + if (mContext.getResources() + .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) { + silenceRingerSetting = Settings.Secure.getIntForUser(mContentResolver, + Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF, + UserHandle.USER_CURRENT); + } + + switch(silenceRingerSetting) { + case VOLUME_HUSH_MUTE: + effect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK); + ringerMode = AudioManager.RINGER_MODE_SILENT; + toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_silent; + break; + case VOLUME_HUSH_VIBRATE: + effect = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); + ringerMode = AudioManager.RINGER_MODE_VIBRATE; + toastText = com.android.internal.R.string.volume_dialog_ringer_guidance_vibrate; + break; + } + maybeVibrate(effect); + setRingerModeInternal(ringerMode, reason); + Toast.makeText(mContext, toastText, Toast.LENGTH_SHORT).show(); + } + + private boolean maybeVibrate(VibrationEffect effect) { + if (!mHasVibrator) { + return false; + } + final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0; + if (hapticsDisabled) { + return false; + } + + if (effect == null) { + return false; + } + mVibrator.vibrate( + Binder.getCallingUid(), mContext.getOpPackageName(), effect, VIBRATION_ATTRIBUTES); + return true; + } + private void setRingerMode(int ringerMode, String caller, boolean external) { if (mUseFixedVolume || mIsSingleVolume) { return; @@ -7246,6 +7305,11 @@ public class AudioService extends IAudioService.Stub } @Override + public void silenceRingerModeInternal(String caller) { + AudioService.this.silenceRingerModeInternal(caller); + } + + @Override public void updateRingerModeAffectedStreamsInternal() { synchronized (mSettingsLock) { if (updateRingerAndZenModeAffectedStreams()) { diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 6b70f5c4ec88..4c9b5856c93c 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -39,6 +39,7 @@ import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static android.content.res.Configuration.UI_MODE_TYPE_MASK; import static android.os.Build.VERSION_CODES.M; import static android.os.Build.VERSION_CODES.O; +import static android.provider.Settings.Secure.VOLUME_HUSH_OFF; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.STATE_OFF; import static android.view.WindowManager.DOCKED_LEFT; @@ -187,6 +188,7 @@ import android.hardware.input.InputManagerInternal; import android.hardware.power.V1_0.PowerHint; import android.media.AudioAttributes; import android.media.AudioManager; +import android.media.AudioManagerInternal; import android.media.AudioSystem; import android.media.IAudioService; import android.media.session.MediaSessionLegacyHelper; @@ -455,6 +457,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { PowerManagerInternal mPowerManagerInternal; IStatusBarService mStatusBarService; StatusBarManagerInternal mStatusBarManagerInternal; + AudioManagerInternal mAudioManagerInternal; boolean mPreloadedRecentApps; final Object mServiceAquireLock = new Object(); Vibrator mVibrator; // Vibrator for giving feedback of orientation changes @@ -772,6 +775,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean mScreenshotChordPowerKeyTriggered; private long mScreenshotChordPowerKeyTime; + // Ringer toggle should reuse timing and triggering from screenshot power and a11y vol up + private int mRingerToggleChord = VOLUME_HUSH_OFF; + private static final long BUGREPORT_TV_GESTURE_TIMEOUT_MILLIS = 1000; private boolean mBugreportTvKey1Pressed; @@ -836,6 +842,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { private static final int MSG_LAUNCH_ASSIST_LONG_PRESS = 27; private static final int MSG_POWER_VERY_LONG_PRESS = 28; private static final int MSG_NOTIFY_USER_ACTIVITY = 29; + private static final int MSG_RINGER_TOGGLE_CHORD = 30; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS = 0; private static final int MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION = 1; @@ -943,6 +950,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); mContext.sendBroadcastAsUser(intent, UserHandle.ALL, android.Manifest.permission.USER_ACTIVITY); + case MSG_RINGER_TOGGLE_CHORD: + handleRingerChordGesture(); break; } } @@ -996,6 +1005,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Secure.getUriFor( Settings.Secure.SHOW_ROTATION_SUGGESTIONS), false, this, UserHandle.USER_ALL); + resolver.registerContentObserver(Settings.Secure.getUriFor( + Settings.Secure.VOLUME_HUSH_GESTURE), false, this, + UserHandle.USER_ALL); resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.POLICY_CONTROL), false, this, UserHandle.USER_ALL); @@ -1117,6 +1129,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { @VisibleForTesting SystemGesturesPointerEventListener mSystemGestures; + private void handleRingerChordGesture() { + if (mRingerToggleChord == VOLUME_HUSH_OFF) { + return; + } + getAudioManagerInternal(); + mAudioManagerInternal.silenceRingerModeInternal("volume_hush"); + } + IStatusBarService getStatusBarService() { synchronized (mServiceAquireLock) { if (mStatusBarService == null) { @@ -1137,6 +1157,15 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + AudioManagerInternal getAudioManagerInternal() { + synchronized (mServiceAquireLock) { + if (mAudioManagerInternal == null) { + mAudioManagerInternal = LocalServices.getService(AudioManagerInternal.class); + } + return mAudioManagerInternal; + } + } + /* * We always let the sensor be switched on by default except when * the user has explicitly disabled sensor based rotation or when the @@ -1306,6 +1335,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { mScreenshotChordPowerKeyTriggered = true; mScreenshotChordPowerKeyTime = event.getDownTime(); interceptScreenshotChord(); + interceptRingerToggleChord(); } // Stop ringing or end call if configured to do so when power is pressed. @@ -1701,6 +1731,22 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + private void interceptRingerToggleChord() { + if (mRingerToggleChord != Settings.Secure.VOLUME_HUSH_OFF + && mScreenshotChordPowerKeyTriggered && mA11yShortcutChordVolumeUpKeyTriggered) { + final long now = SystemClock.uptimeMillis(); + if (now <= mA11yShortcutChordVolumeUpKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS + && now <= mScreenshotChordPowerKeyTime + + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) { + mA11yShortcutChordVolumeUpKeyConsumed = true; + cancelPendingPowerKeyAction(); + + mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_RINGER_TOGGLE_CHORD), + getRingerToggleChordDelay()); + } + } + } + private long getAccessibilityShortcutTimeout() { ViewConfiguration config = ViewConfiguration.get(mContext); return Settings.Secure.getIntForUser(mContext.getContentResolver(), @@ -1718,6 +1764,11 @@ public class PhoneWindowManager implements WindowManagerPolicy { return ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout(); } + private long getRingerToggleChordDelay() { + // Always timeout like a tap + return ViewConfiguration.getTapTimeout(); + } + private void cancelPendingScreenshotChordAction() { mHandler.removeCallbacks(mScreenshotRunnable); } @@ -1726,6 +1777,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { mHandler.removeMessages(MSG_ACCESSIBILITY_SHORTCUT); } + private void cancelPendingRingerToggleChordAction() { + mHandler.removeMessages(MSG_RINGER_TOGGLE_CHORD); + } + private final Runnable mEndCallLongPress = new Runnable() { @Override public void run() { @@ -2382,7 +2437,13 @@ public class PhoneWindowManager implements WindowManagerPolicy { mSystemNavigationKeysEnabled = Settings.Secure.getIntForUser(resolver, Settings.Secure.SYSTEM_NAVIGATION_KEYS_ENABLED, 0, UserHandle.USER_CURRENT) == 1; - + mRingerToggleChord = Settings.Secure.getIntForUser(resolver, + Settings.Secure.VOLUME_HUSH_GESTURE, VOLUME_HUSH_OFF, + UserHandle.USER_CURRENT); + if (!mContext.getResources() + .getBoolean(com.android.internal.R.bool.config_volumeHushGestureEnabled)) { + mRingerToggleChord = Settings.Secure.VOLUME_HUSH_OFF; + } // Configure rotation suggestions. int showRotationSuggestions = Settings.Secure.getIntForUser(resolver, Settings.Secure.SHOW_ROTATION_SUGGESTIONS, @@ -3531,6 +3592,25 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } + // If a ringer toggle chord could be on the way but we're not sure, then tell the dispatcher + // to wait a little while and try again later before dispatching. + if (mRingerToggleChord != VOLUME_HUSH_OFF && (flags & KeyEvent.FLAG_FALLBACK) == 0) { + if (mA11yShortcutChordVolumeUpKeyTriggered && !mScreenshotChordPowerKeyTriggered) { + final long now = SystemClock.uptimeMillis(); + final long timeoutTime = mA11yShortcutChordVolumeUpKeyTime + + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS; + if (now < timeoutTime) { + return timeoutTime - now; + } + } + if (keyCode == KeyEvent.KEYCODE_VOLUME_UP && mA11yShortcutChordVolumeUpKeyConsumed) { + if (!down) { + mA11yShortcutChordVolumeUpKeyConsumed = false; + } + return -1; + } + } + // Cancel any pending meta actions if we see any other keys being pressed between the down // of the meta key and its corresponding up. if (mPendingMetaAction && !KeyEvent.isMetaKey(keyCode)) { @@ -5997,6 +6077,9 @@ public class PhoneWindowManager implements WindowManagerPolicy { case KeyEvent.KEYCODE_VOLUME_MUTE: { if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { if (down) { + // Any activity on the vol down button stops the ringer toggle shortcut + cancelPendingRingerToggleChordAction(); + if (interactive && !mScreenshotChordVolumeDownKeyTriggered && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { mScreenshotChordVolumeDownKeyTriggered = true; @@ -6020,12 +6103,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { mA11yShortcutChordVolumeUpKeyConsumed = false; cancelPendingPowerKeyAction(); cancelPendingScreenshotChordAction(); + cancelPendingRingerToggleChordAction(); + interceptAccessibilityShortcutChord(); + interceptRingerToggleChord(); } } else { mA11yShortcutChordVolumeUpKeyTriggered = false; cancelPendingScreenshotChordAction(); cancelPendingAccessibilityShortcutAction(); + cancelPendingRingerToggleChordAction(); } } if (down) { |