Merge "Using performHapticFeedback on UdfpsController" into udc-qpr-dev am: 2588c8d5be

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/24285290

Change-Id: I5749c842d375da54151a3a02a0ddbae7e0553e61
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Juan Sebastian Martinez
2023-08-01 23:46:59 +00:00
committed by Automerger Merge Worker
2 changed files with 142 additions and 12 deletions

View File

@@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricOverlayConstants.REASON_ENROL
import static com.android.internal.util.Preconditions.checkNotNull;
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.Context;
@@ -50,6 +51,7 @@ import android.os.Trace;
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
@@ -234,6 +236,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {
public static final 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() {
@Override
public void onScreenTurnedOn() {
@@ -926,12 +930,24 @@ public class UdfpsController implements DozeReceiver, Dumpable {
@VisibleForTesting
public void playStartHaptic() {
if (mAccessibilityManager.isTouchExplorationEnabled()) {
mVibrator.vibrate(
Process.myUid(),
mContext.getOpPackageName(),
EFFECT_CLICK,
"udfps-onStart-click",
UDFPS_VIBRATION_ATTRIBUTES);
if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
if (mOverlay != null && mOverlay.getOverlayView() != null) {
mVibrator.performHapticFeedback(
mOverlay.getOverlayView(),
HapticFeedbackConstants.CONTEXT_CLICK
);
} 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);
// play the same haptic as the LockIconViewController longpress
mVibrator.vibrate(
Process.myUid(),
mContext.getOpPackageName(),
UdfpsController.EFFECT_CLICK,
"aod-lock-icon-longpress",
LOCK_ICON_VIBRATION_ATTRIBUTES);
if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) {
if (mOverlay != null && mOverlay.getOverlayView() != null) {
mVibrator.performHapticFeedback(
mOverlay.getOverlayView(),
UdfpsController.LONG_PRESS
);
} 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;
}

View File

@@ -23,6 +23,7 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.internal.util.FunctionalUtils.ThrowingConsumer;
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.assertFalse;
@@ -61,6 +62,7 @@ import android.os.RemoteException;
import android.os.VibrationAttributes;
import android.testing.TestableLooper.RunWithLooper;
import android.util.Pair;
import android.view.HapticFeedbackConstants;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
@@ -1127,6 +1129,36 @@ public class UdfpsControllerTest extends SysuiTestCase {
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
public void noHapticOnTouchUdfpsArea_a11yTouchExplorationDisabled() throws RemoteException {
// Configure UdfpsView to accept the ACTION_DOWN event
@@ -1159,6 +1191,35 @@ public class UdfpsControllerTest extends SysuiTestCase {
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
public void onTouch_withoutNewTouchDetection_shouldCallOldFingerprintManagerPath()
throws RemoteException {
@@ -1514,4 +1575,45 @@ public class UdfpsControllerTest extends SysuiTestCase {
// THEN is fingerDown should be FALSE
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));
}
}