Merge "Add power button cooldown after emergency gesture is triggered." into sc-v2-dev am: 7f62909c98
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/16722352 Change-Id: I29d1ca769454e06f0cb98bf3bcb679ae162b432a
This commit is contained in:
@@ -9193,6 +9193,16 @@ public final class Settings {
|
|||||||
public static final String EMERGENCY_GESTURE_SOUND_ENABLED =
|
public static final String EMERGENCY_GESTURE_SOUND_ENABLED =
|
||||||
"emergency_gesture_sound_enabled";
|
"emergency_gesture_sound_enabled";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The power button "cooldown" period in milliseconds after the Emergency gesture is
|
||||||
|
* triggered, during which single-key actions on the power button are suppressed. Cooldown
|
||||||
|
* period is disabled if set to zero.
|
||||||
|
*
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final String EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS =
|
||||||
|
"emergency_gesture_power_button_cooldown_period_ms";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the camera launch gesture to double tap the power button when the screen is off
|
* Whether the camera launch gesture to double tap the power button when the screen is off
|
||||||
* should be disabled.
|
* should be disabled.
|
||||||
|
|||||||
@@ -272,6 +272,8 @@ public class SecureSettingsValidators {
|
|||||||
VALIDATORS.put(Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
|
VALIDATORS.put(Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, BOOLEAN_VALIDATOR);
|
||||||
VALIDATORS.put(Secure.EMERGENCY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
|
VALIDATORS.put(Secure.EMERGENCY_GESTURE_ENABLED, BOOLEAN_VALIDATOR);
|
||||||
VALIDATORS.put(Secure.EMERGENCY_GESTURE_SOUND_ENABLED, BOOLEAN_VALIDATOR);
|
VALIDATORS.put(Secure.EMERGENCY_GESTURE_SOUND_ENABLED, BOOLEAN_VALIDATOR);
|
||||||
|
VALIDATORS.put(Secure.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS,
|
||||||
|
NON_NEGATIVE_INTEGER_VALIDATOR);
|
||||||
VALIDATORS.put(Secure.ADAPTIVE_CONNECTIVITY_ENABLED, BOOLEAN_VALIDATOR);
|
VALIDATORS.put(Secure.ADAPTIVE_CONNECTIVITY_ENABLED, BOOLEAN_VALIDATOR);
|
||||||
VALIDATORS.put(
|
VALIDATORS.put(
|
||||||
Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS, NONE_NEGATIVE_LONG_VALIDATOR);
|
Secure.ASSIST_HANDLES_LEARNING_TIME_ELAPSED_MILLIS, NONE_NEGATIVE_LONG_VALIDATOR);
|
||||||
|
|||||||
@@ -82,6 +82,20 @@ public class GestureLauncherService extends SystemService {
|
|||||||
*/
|
*/
|
||||||
private static final int EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD = 5;
|
private static final int EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD = 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default value of the power button "cooldown" period after the Emergency gesture is triggered.
|
||||||
|
* See {@link Settings.Secure#EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS}
|
||||||
|
*/
|
||||||
|
private static final int EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_DEFAULT = 3000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maximum value of the power button "cooldown" period after the Emergency gesture is triggered.
|
||||||
|
* The value read from {@link Settings.Secure#EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS}
|
||||||
|
* is capped at this maximum.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
static final int EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX = 5000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of taps required to launch camera shortcut.
|
* Number of taps required to launch camera shortcut.
|
||||||
*/
|
*/
|
||||||
@@ -145,7 +159,14 @@ public class GestureLauncherService extends SystemService {
|
|||||||
*/
|
*/
|
||||||
private boolean mEmergencyGestureEnabled;
|
private boolean mEmergencyGestureEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Power button cooldown period in milliseconds, after emergency gesture is triggered. A zero
|
||||||
|
* value means the cooldown period is disabled.
|
||||||
|
*/
|
||||||
|
private int mEmergencyGesturePowerButtonCooldownPeriodMs;
|
||||||
|
|
||||||
private long mLastPowerDown;
|
private long mLastPowerDown;
|
||||||
|
private long mLastEmergencyGestureTriggered;
|
||||||
private int mPowerButtonConsecutiveTaps;
|
private int mPowerButtonConsecutiveTaps;
|
||||||
private int mPowerButtonSlowConsecutiveTaps;
|
private int mPowerButtonSlowConsecutiveTaps;
|
||||||
private final UiEventLogger mUiEventLogger;
|
private final UiEventLogger mUiEventLogger;
|
||||||
@@ -210,6 +231,7 @@ public class GestureLauncherService extends SystemService {
|
|||||||
updateCameraRegistered();
|
updateCameraRegistered();
|
||||||
updateCameraDoubleTapPowerEnabled();
|
updateCameraDoubleTapPowerEnabled();
|
||||||
updateEmergencyGestureEnabled();
|
updateEmergencyGestureEnabled();
|
||||||
|
updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
mUserId = ActivityManager.getCurrentUser();
|
mUserId = ActivityManager.getCurrentUser();
|
||||||
mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
|
mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED));
|
||||||
@@ -230,6 +252,10 @@ public class GestureLauncherService extends SystemService {
|
|||||||
mContext.getContentResolver().registerContentObserver(
|
mContext.getContentResolver().registerContentObserver(
|
||||||
Settings.Secure.getUriFor(Settings.Secure.EMERGENCY_GESTURE_ENABLED),
|
Settings.Secure.getUriFor(Settings.Secure.EMERGENCY_GESTURE_ENABLED),
|
||||||
false, mSettingObserver, mUserId);
|
false, mSettingObserver, mUserId);
|
||||||
|
mContext.getContentResolver().registerContentObserver(
|
||||||
|
Settings.Secure.getUriFor(
|
||||||
|
Settings.Secure.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS),
|
||||||
|
false, mSettingObserver, mUserId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateCameraRegistered() {
|
private void updateCameraRegistered() {
|
||||||
@@ -263,6 +289,14 @@ public class GestureLauncherService extends SystemService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
void updateEmergencyGesturePowerButtonCooldownPeriodMs() {
|
||||||
|
int cooldownPeriodMs = getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, mUserId);
|
||||||
|
synchronized (this) {
|
||||||
|
mEmergencyGesturePowerButtonCooldownPeriodMs = cooldownPeriodMs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void unregisterCameraLaunchGesture() {
|
private void unregisterCameraLaunchGesture() {
|
||||||
if (mCameraLaunchRegistered) {
|
if (mCameraLaunchRegistered) {
|
||||||
mCameraLaunchRegistered = false;
|
mCameraLaunchRegistered = false;
|
||||||
@@ -397,6 +431,20 @@ public class GestureLauncherService extends SystemService {
|
|||||||
Settings.Secure.EMERGENCY_GESTURE_ENABLED, 1, userId) != 0;
|
Settings.Secure.EMERGENCY_GESTURE_ENABLED, 1, userId) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets power button cooldown period in milliseconds after emergency gesture is triggered. The
|
||||||
|
* value is capped at a maximum
|
||||||
|
* {@link GestureLauncherService#EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX}. If the
|
||||||
|
* value is zero, it means the cooldown period is disabled.
|
||||||
|
*/
|
||||||
|
@VisibleForTesting
|
||||||
|
static int getEmergencyGesturePowerButtonCooldownPeriodMs(Context context, int userId) {
|
||||||
|
int cooldown = Settings.Secure.getIntForUser(context.getContentResolver(),
|
||||||
|
Settings.Secure.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS,
|
||||||
|
EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_DEFAULT, userId);
|
||||||
|
return Math.min(cooldown, EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to enable the camera launch gesture.
|
* Whether to enable the camera launch gesture.
|
||||||
*/
|
*/
|
||||||
@@ -445,10 +493,24 @@ public class GestureLauncherService extends SystemService {
|
|||||||
*/
|
*/
|
||||||
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
|
public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
|
||||||
MutableBoolean outLaunched) {
|
MutableBoolean outLaunched) {
|
||||||
|
if (mEmergencyGestureEnabled && mEmergencyGesturePowerButtonCooldownPeriodMs >= 0
|
||||||
|
&& event.getEventTime() - mLastEmergencyGestureTriggered
|
||||||
|
< mEmergencyGesturePowerButtonCooldownPeriodMs) {
|
||||||
|
Slog.i(TAG, String.format(
|
||||||
|
"Suppressing power button: within %dms cooldown period after Emergency "
|
||||||
|
+ "Gesture. Begin=%dms, end=%dms.",
|
||||||
|
mEmergencyGesturePowerButtonCooldownPeriodMs,
|
||||||
|
mLastEmergencyGestureTriggered,
|
||||||
|
mLastEmergencyGestureTriggered + mEmergencyGesturePowerButtonCooldownPeriodMs));
|
||||||
|
outLaunched.value = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (event.isLongPress()) {
|
if (event.isLongPress()) {
|
||||||
// Long presses are sent as a second key down. If the long press threshold is set lower
|
// Long presses are sent as a second key down. If the long press threshold is set lower
|
||||||
// than the double tap of sequence interval thresholds, this could cause false double
|
// than the double tap of sequence interval thresholds, this could cause false double
|
||||||
// taps or consecutive taps, so we want to ignore the long press event.
|
// taps or consecutive taps, so we want to ignore the long press event.
|
||||||
|
outLaunched.value = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
boolean launchCamera = false;
|
boolean launchCamera = false;
|
||||||
@@ -509,6 +571,12 @@ public class GestureLauncherService extends SystemService {
|
|||||||
Slog.i(TAG, "Emergency gesture detected, launching.");
|
Slog.i(TAG, "Emergency gesture detected, launching.");
|
||||||
launchEmergencyGesture = handleEmergencyGesture();
|
launchEmergencyGesture = handleEmergencyGesture();
|
||||||
mUiEventLogger.log(GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER);
|
mUiEventLogger.log(GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER);
|
||||||
|
// Record emergency trigger time if emergency UI was launched
|
||||||
|
if (launchEmergencyGesture) {
|
||||||
|
synchronized (this) {
|
||||||
|
mLastEmergencyGestureTriggered = event.getEventTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mMetricsLogger.histogram("power_consecutive_short_tap_count",
|
mMetricsLogger.histogram("power_consecutive_short_tap_count",
|
||||||
mPowerButtonSlowConsecutiveTaps);
|
mPowerButtonSlowConsecutiveTaps);
|
||||||
@@ -600,6 +668,7 @@ public class GestureLauncherService extends SystemService {
|
|||||||
updateCameraRegistered();
|
updateCameraRegistered();
|
||||||
updateCameraDoubleTapPowerEnabled();
|
updateCameraDoubleTapPowerEnabled();
|
||||||
updateEmergencyGestureEnabled();
|
updateEmergencyGestureEnabled();
|
||||||
|
updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -610,6 +679,7 @@ public class GestureLauncherService extends SystemService {
|
|||||||
updateCameraRegistered();
|
updateCameraRegistered();
|
||||||
updateCameraDoubleTapPowerEnabled();
|
updateCameraDoubleTapPowerEnabled();
|
||||||
updateEmergencyGestureEnabled();
|
updateEmergencyGestureEnabled();
|
||||||
|
updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -186,6 +186,30 @@ public class GestureLauncherServiceTest {
|
|||||||
mContext, FAKE_USER_ID));
|
mContext, FAKE_USER_ID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_enabled() {
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(4000);
|
||||||
|
assertEquals(4000,
|
||||||
|
mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext,
|
||||||
|
FAKE_USER_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_disabled() {
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(0);
|
||||||
|
assertEquals(0,
|
||||||
|
mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext,
|
||||||
|
FAKE_USER_ID));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_cappedAtMaximum() {
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(10000);
|
||||||
|
assertEquals(GestureLauncherService.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX,
|
||||||
|
mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext,
|
||||||
|
FAKE_USER_ID));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testHandleCameraLaunchGesture_userSetupComplete() {
|
public void testHandleCameraLaunchGesture_userSetupComplete() {
|
||||||
withUserSetupCompleteValue(true);
|
withUserSetupCompleteValue(true);
|
||||||
@@ -644,6 +668,211 @@ public class GestureLauncherServiceTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptPowerKeyDown_triggerEmergency_singleTaps_cooldownTriggered() {
|
||||||
|
// Enable power button cooldown
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000);
|
||||||
|
mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
|
// Trigger emergency by tapping button 5 times
|
||||||
|
long eventTime = triggerEmergencyGesture();
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Subsequent single tap is intercepted, but should not trigger any gesture
|
||||||
|
KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT);
|
||||||
|
boolean interactive = true;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(true);
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertTrue(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Another single tap should be the same (intercepted but should not trigger gesture)
|
||||||
|
keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT);
|
||||||
|
interactive = true;
|
||||||
|
outLaunched = new MutableBoolean(true);
|
||||||
|
intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertTrue(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
testInterceptPowerKeyDown_triggerEmergency_cameraGestureEnabled_doubleTap_cooldownTriggered() {
|
||||||
|
// Enable camera double tap gesture
|
||||||
|
withCameraDoubleTapPowerEnableConfigValue(true);
|
||||||
|
withCameraDoubleTapPowerDisableSettingValue(0);
|
||||||
|
mGestureLauncherService.updateCameraDoubleTapPowerEnabled();
|
||||||
|
|
||||||
|
// Enable power button cooldown
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000);
|
||||||
|
mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
|
// Trigger emergency by tapping button 5 times
|
||||||
|
long eventTime = triggerEmergencyGesture();
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Subsequent double tap is intercepted, but should not trigger any gesture
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION,
|
||||||
|
IGNORED_CODE, IGNORED_REPEAT);
|
||||||
|
boolean interactive = true;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(true);
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent,
|
||||||
|
interactive, outLaunched);
|
||||||
|
assertTrue(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
|
||||||
|
eventTime += interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptPowerKeyDown_triggerEmergency_fiveTaps_cooldownTriggered() {
|
||||||
|
// Enable power button cooldown
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000);
|
||||||
|
mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
|
// Trigger emergency by tapping button 5 times
|
||||||
|
long eventTime = triggerEmergencyGesture();
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Subsequent 5 taps are intercepted, but should not trigger any gesture
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION,
|
||||||
|
IGNORED_CODE, IGNORED_REPEAT);
|
||||||
|
boolean interactive = true;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(true);
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent,
|
||||||
|
interactive, outLaunched);
|
||||||
|
assertTrue(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
|
||||||
|
eventTime += interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptPowerKeyDown_triggerEmergency_longPress_cooldownTriggered() {
|
||||||
|
// Enable power button cooldown
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000);
|
||||||
|
mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
|
// Trigger emergency by tapping button 5 times
|
||||||
|
long eventTime = triggerEmergencyGesture();
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Subsequent long press is intercepted, but should not trigger any gesture
|
||||||
|
KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE,
|
||||||
|
KeyEvent.FLAG_LONG_PRESS);
|
||||||
|
|
||||||
|
boolean interactive = true;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(true);
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertTrue(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInterceptPowerKeyDown_triggerEmergency_cooldownDisabled_cooldownNotTriggered() {
|
||||||
|
// Disable power button cooldown by setting cooldown period to 0
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(0);
|
||||||
|
mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
|
// Trigger emergency by tapping button 5 times
|
||||||
|
long eventTime = triggerEmergencyGesture();
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Subsequent single tap is NOT intercepted
|
||||||
|
KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT);
|
||||||
|
boolean interactive = true;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(true);
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertFalse(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Long press also NOT intercepted
|
||||||
|
keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE,
|
||||||
|
KeyEvent.FLAG_LONG_PRESS);
|
||||||
|
interactive = true;
|
||||||
|
outLaunched = new MutableBoolean(true);
|
||||||
|
intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertFalse(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void
|
||||||
|
testInterceptPowerKeyDown_triggerEmergency_outsideCooldownPeriod_cooldownNotTriggered() {
|
||||||
|
// Enable power button cooldown
|
||||||
|
withEmergencyGesturePowerButtonCooldownPeriodMsValue(5000);
|
||||||
|
mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs();
|
||||||
|
|
||||||
|
// Trigger emergency by tapping button 5 times
|
||||||
|
long eventTime = triggerEmergencyGesture();
|
||||||
|
|
||||||
|
// Add enough interval to be outside of cooldown period
|
||||||
|
long interval = 5001;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Subsequent single tap is NOT intercepted
|
||||||
|
KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT);
|
||||||
|
boolean interactive = true;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(true);
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertFalse(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
|
||||||
|
// Add enough interval to reset consecutive tap count
|
||||||
|
interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1;
|
||||||
|
eventTime += interval;
|
||||||
|
|
||||||
|
// Long press also NOT intercepted
|
||||||
|
keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE,
|
||||||
|
KeyEvent.FLAG_LONG_PRESS);
|
||||||
|
interactive = true;
|
||||||
|
outLaunched = new MutableBoolean(true);
|
||||||
|
intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertFalse(intercepted);
|
||||||
|
assertFalse(outLaunched.value);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInterceptPowerKeyDown_longpress() {
|
public void testInterceptPowerKeyDown_longpress() {
|
||||||
withCameraDoubleTapPowerEnableConfigValue(true);
|
withCameraDoubleTapPowerEnableConfigValue(true);
|
||||||
@@ -1153,6 +1382,45 @@ public class GestureLauncherServiceTest {
|
|||||||
assertEquals(1, tapCounts.get(1).intValue());
|
assertEquals(1, tapCounts.get(1).intValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to trigger emergency gesture by pressing button for 5 times.
|
||||||
|
* @return last event time.
|
||||||
|
*/
|
||||||
|
private long triggerEmergencyGesture() {
|
||||||
|
// Enable emergency power gesture
|
||||||
|
withEmergencyGestureEnabledConfigValue(true);
|
||||||
|
withEmergencyGestureEnabledSettingValue(true);
|
||||||
|
mGestureLauncherService.updateEmergencyGestureEnabled();
|
||||||
|
withUserSetupCompleteValue(true);
|
||||||
|
|
||||||
|
// 4 button presses
|
||||||
|
long eventTime = INITIAL_EVENT_TIME_MILLIS;
|
||||||
|
boolean interactive = true;
|
||||||
|
KeyEvent keyEvent;
|
||||||
|
MutableBoolean outLaunched = new MutableBoolean(false);
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT);
|
||||||
|
mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched);
|
||||||
|
final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1;
|
||||||
|
eventTime += interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5th button press should trigger the emergency flow
|
||||||
|
keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE,
|
||||||
|
IGNORED_REPEAT);
|
||||||
|
outLaunched.value = false;
|
||||||
|
boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive,
|
||||||
|
outLaunched);
|
||||||
|
assertTrue(outLaunched.value);
|
||||||
|
assertTrue(intercepted);
|
||||||
|
verify(mUiEventLogger, times(1))
|
||||||
|
.log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER);
|
||||||
|
verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected();
|
||||||
|
|
||||||
|
return eventTime;
|
||||||
|
}
|
||||||
|
|
||||||
private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) {
|
private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) {
|
||||||
when(mResources.getBoolean(
|
when(mResources.getBoolean(
|
||||||
com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled))
|
com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled))
|
||||||
@@ -1181,6 +1449,14 @@ public class GestureLauncherServiceTest {
|
|||||||
UserHandle.USER_CURRENT);
|
UserHandle.USER_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void withEmergencyGesturePowerButtonCooldownPeriodMsValue(int period) {
|
||||||
|
Settings.Secure.putIntForUser(
|
||||||
|
mContentResolver,
|
||||||
|
Settings.Secure.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS,
|
||||||
|
period,
|
||||||
|
UserHandle.USER_CURRENT);
|
||||||
|
}
|
||||||
|
|
||||||
private void withUserSetupCompleteValue(boolean userSetupComplete) {
|
private void withUserSetupCompleteValue(boolean userSetupComplete) {
|
||||||
int userSetupCompleteValue = userSetupComplete ? 1 : 0;
|
int userSetupCompleteValue = userSetupComplete ? 1 : 0;
|
||||||
Settings.Secure.putIntForUser(
|
Settings.Secure.putIntForUser(
|
||||||
|
|||||||
Reference in New Issue
Block a user