Merge "Using performHapticFeedback on UdfpsController" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
2588c8d5be
@@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROL
|
|||||||
|
|
||||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||||
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
|
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
|
||||||
|
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -50,6 +51,7 @@ import android.os.Trace;
|
|||||||
import android.os.VibrationAttributes;
|
import android.os.VibrationAttributes;
|
||||||
import android.os.VibrationEffect;
|
import android.os.VibrationEffect;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.VelocityTracker;
|
import android.view.VelocityTracker;
|
||||||
@@ -234,6 +236,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
|||||||
public static final VibrationEffect EFFECT_CLICK =
|
public static final VibrationEffect EFFECT_CLICK =
|
||||||
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
|
VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
|
||||||
|
|
||||||
|
public static final int LONG_PRESS = HapticFeedbackConstants.LONG_PRESS;
|
||||||
|
|
||||||
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
|
private final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
|
||||||
@Override
|
@Override
|
||||||
public void onScreenTurnedOn() {
|
public void onScreenTurnedOn() {
|
||||||
@@ -926,12 +930,24 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
|||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public void playStartHaptic() {
|
public void playStartHaptic() {
|
||||||
if (mAccessibilityManager.isTouchExplorationEnabled()) {
|
if (mAccessibilityManager.isTouchExplorationEnabled()) {
|
||||||
mVibrator.vibrate(
|
if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
|
||||||
Process.myUid(),
|
if (mOverlay != null && mOverlay.getOverlayView() != null) {
|
||||||
mContext.getOpPackageName(),
|
mVibrator.performHapticFeedback(
|
||||||
EFFECT_CLICK,
|
mOverlay.getOverlayView(),
|
||||||
"udfps-onStart-click",
|
HapticFeedbackConstants.CONTEXT_CLICK
|
||||||
UDFPS_VIBRATION_ATTRIBUTES);
|
);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "No haptics played. Could not obtain overlay view to perform"
|
||||||
|
+ "vibration. Either the controller overlay is null or has no view");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mVibrator.vibrate(
|
||||||
|
Process.myUid(),
|
||||||
|
mContext.getOpPackageName(),
|
||||||
|
EFFECT_CLICK,
|
||||||
|
"udfps-onStart-click",
|
||||||
|
UDFPS_VIBRATION_ATTRIBUTES);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1024,12 +1040,24 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
|||||||
mKeyguardViewManager.showPrimaryBouncer(true);
|
mKeyguardViewManager.showPrimaryBouncer(true);
|
||||||
|
|
||||||
// play the same haptic as the LockIconViewController longpress
|
// play the same haptic as the LockIconViewController longpress
|
||||||
mVibrator.vibrate(
|
if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
|
||||||
Process.myUid(),
|
if (mOverlay != null && mOverlay.getOverlayView() != null) {
|
||||||
mContext.getOpPackageName(),
|
mVibrator.performHapticFeedback(
|
||||||
UdfpsController.EFFECT_CLICK,
|
mOverlay.getOverlayView(),
|
||||||
"aod-lock-icon-longpress",
|
UdfpsController.LONG_PRESS
|
||||||
LOCK_ICON_VIBRATION_ATTRIBUTES);
|
);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "No haptics played. Could not obtain overlay view to perform"
|
||||||
|
+ "vibration. Either the controller overlay is null or has no view");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mVibrator.vibrate(
|
||||||
|
Process.myUid(),
|
||||||
|
mContext.getOpPackageName(),
|
||||||
|
UdfpsController.EFFECT_CLICK,
|
||||||
|
"aod-lock-icon-longpress",
|
||||||
|
LOCK_ICON_VIBRATION_ATTRIBUTES);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import static android.view.MotionEvent.ACTION_UP;
|
|||||||
|
|
||||||
import static com.android.internal.util.FunctionalUtils.ThrowingConsumer;
|
import static com.android.internal.util.FunctionalUtils.ThrowingConsumer;
|
||||||
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
|
import static com.android.systemui.classifier.Classifier.UDFPS_AUTHENTICATION;
|
||||||
|
import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
import static junit.framework.Assert.assertFalse;
|
import static junit.framework.Assert.assertFalse;
|
||||||
@@ -61,6 +62,7 @@ import android.os.RemoteException;
|
|||||||
import android.os.VibrationAttributes;
|
import android.os.VibrationAttributes;
|
||||||
import android.testing.TestableLooper.RunWithLooper;
|
import android.testing.TestableLooper.RunWithLooper;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
import android.view.HapticFeedbackConstants;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
@@ -1127,6 +1129,36 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
|||||||
UdfpsController.UDFPS_VIBRATION_ATTRIBUTES.getUsage());
|
UdfpsController.UDFPS_VIBRATION_ATTRIBUTES.getUsage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playHapticOnTouchUdfpsArea_a11yTouchExplorationEnabled_oneWayHapticsEnabled()
|
||||||
|
throws RemoteException {
|
||||||
|
when(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true);
|
||||||
|
// Configure UdfpsView to accept the ACTION_DOWN event
|
||||||
|
when(mUdfpsView.isDisplayConfigured()).thenReturn(false);
|
||||||
|
when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
|
||||||
|
|
||||||
|
// GIVEN that the overlay is showing and a11y touch exploration enabled
|
||||||
|
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(true);
|
||||||
|
mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
|
||||||
|
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
|
||||||
|
mFgExecutor.runAllReady();
|
||||||
|
|
||||||
|
// WHEN ACTION_HOVER is received
|
||||||
|
verify(mUdfpsView).setOnHoverListener(mHoverListenerCaptor.capture());
|
||||||
|
MotionEvent enterEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_ENTER, 0, 0, 0);
|
||||||
|
mHoverListenerCaptor.getValue().onHover(mUdfpsView, enterEvent);
|
||||||
|
enterEvent.recycle();
|
||||||
|
MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_HOVER_MOVE, 0, 0, 0);
|
||||||
|
mHoverListenerCaptor.getValue().onHover(mUdfpsView, moveEvent);
|
||||||
|
moveEvent.recycle();
|
||||||
|
|
||||||
|
// THEN context click haptic is played
|
||||||
|
verify(mVibrator).performHapticFeedback(
|
||||||
|
any(),
|
||||||
|
eq(HapticFeedbackConstants.CONTEXT_CLICK)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled() throws RemoteException {
|
public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled() throws RemoteException {
|
||||||
// Configure UdfpsView to accept the ACTION_DOWN event
|
// Configure UdfpsView to accept the ACTION_DOWN event
|
||||||
@@ -1159,6 +1191,35 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
|||||||
any());
|
any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled__oneWayHapticsEnabled()
|
||||||
|
throws RemoteException {
|
||||||
|
when(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true);
|
||||||
|
// Configure UdfpsView to accept the ACTION_DOWN event
|
||||||
|
when(mUdfpsView.isDisplayConfigured()).thenReturn(false);
|
||||||
|
when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
|
||||||
|
|
||||||
|
// GIVEN that the overlay is showing and a11y touch exploration NOT enabled
|
||||||
|
when(mAccessibilityManager.isTouchExplorationEnabled()).thenReturn(false);
|
||||||
|
mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
|
||||||
|
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
|
||||||
|
mFgExecutor.runAllReady();
|
||||||
|
|
||||||
|
// WHEN ACTION_DOWN is received
|
||||||
|
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
|
||||||
|
MotionEvent downEvent = MotionEvent.obtain(0, 0, ACTION_DOWN, 0, 0, 0);
|
||||||
|
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent);
|
||||||
|
mBiometricExecutor.runAllReady();
|
||||||
|
downEvent.recycle();
|
||||||
|
MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0);
|
||||||
|
mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
|
||||||
|
mBiometricExecutor.runAllReady();
|
||||||
|
moveEvent.recycle();
|
||||||
|
|
||||||
|
// THEN NO haptic played
|
||||||
|
verify(mVibrator, never()).performHapticFeedback(any(), anyInt());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void onTouch_withoutNewTouchDetection_shouldCallOldFingerprintManagerPath()
|
public void onTouch_withoutNewTouchDetection_shouldCallOldFingerprintManagerPath()
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
@@ -1514,4 +1575,45 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
|||||||
// THEN is fingerDown should be FALSE
|
// THEN is fingerDown should be FALSE
|
||||||
assertFalse(mUdfpsController.isFingerDown());
|
assertFalse(mUdfpsController.isFingerDown());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playHaptic_onAodInterrupt_oneWayHapticsDisabled_onAcquiredBad_usesVibrate()
|
||||||
|
throws RemoteException {
|
||||||
|
// GIVEN UDFPS overlay is showing
|
||||||
|
mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
|
||||||
|
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
|
||||||
|
mFgExecutor.runAllReady();
|
||||||
|
|
||||||
|
// GIVEN there's been an AoD interrupt
|
||||||
|
when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(false);
|
||||||
|
mScreenObserver.onScreenTurnedOn();
|
||||||
|
mUdfpsController.onAodInterrupt(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// THEN vibrate is used
|
||||||
|
verify(mVibrator).vibrate(
|
||||||
|
anyInt(),
|
||||||
|
anyString(),
|
||||||
|
eq(UdfpsController.EFFECT_CLICK),
|
||||||
|
eq("aod-lock-icon-longpress"),
|
||||||
|
eq(UdfpsController.LOCK_ICON_VIBRATION_ATTRIBUTES)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void playHaptic_onAodInterrupt_oneWayHapticsEnabled_onAcquiredBad_performHapticFeedback()
|
||||||
|
throws RemoteException {
|
||||||
|
when(mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)).thenReturn(true);
|
||||||
|
// GIVEN UDFPS overlay is showing
|
||||||
|
mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, mOpticalProps.sensorId,
|
||||||
|
BiometricOverlayConstants.REASON_AUTH_KEYGUARD, mUdfpsOverlayControllerCallback);
|
||||||
|
mFgExecutor.runAllReady();
|
||||||
|
|
||||||
|
// GIVEN there's been an AoD interrupt
|
||||||
|
when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(false);
|
||||||
|
mScreenObserver.onScreenTurnedOn();
|
||||||
|
mUdfpsController.onAodInterrupt(0, 0, 0, 0);
|
||||||
|
|
||||||
|
// THEN vibrate is used
|
||||||
|
verify(mVibrator).performHapticFeedback(any(), eq(UdfpsController.LONG_PRESS));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user