From afa5fd51a57ba3ef5ad373f3c6b297e4c14dde73 Mon Sep 17 00:00:00 2001 From: Juan Sebastian Martinez Date: Wed, 2 Aug 2023 11:39:00 -0700 Subject: [PATCH] Using performHapticFeedback on LockIconViewController Moving towards new haptics API that triggers haptics directly from the UI thread. The LockIconViewController can use the new performHapticFeedback method in the events of (DOWN) HOVER_ENTER and (MOVE) HOVER_MOVE (via LongPress). The haptics for the HOVER_ENTER event use the CONTEXT_CLICK constant. Consistent with the intended behavior and relation to the UdfpsController, haptics for the case of a long press (due to HOVER_MOVE) use the LONG_PRESS constant. The changes are controlled by a feature flag. Test: Tests were added to the LockIconViewControllerTest class to verify the use of old and new vibration methods on the above events. Bug: 245528624 Change-Id: I6ab402df7339df33b4ee54585478d75ff9ffac40 --- .../keyguard/LockIconViewController.java | 49 +++++++++++---- .../keyguard/LockIconViewControllerTest.java | 59 +++++++++++++++++++ 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java index 54597185f8556..d85faefa40e82 100644 --- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java @@ -25,6 +25,7 @@ import static com.android.keyguard.LockIconView.ICON_UNLOCK; import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; import static com.android.systemui.flags.Flags.DOZING_MIGRATION_1; import static com.android.systemui.flags.Flags.LOCKSCREEN_WALLPAPER_DREAM_ENABLED; +import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION; import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow; import android.content.res.Configuration; @@ -39,6 +40,7 @@ import android.os.VibrationAttributes; import android.util.DisplayMetrics; import android.util.Log; import android.util.MathUtils; +import android.view.HapticFeedbackConstants; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; @@ -610,12 +612,7 @@ public class LockIconViewController extends ViewController impleme case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_HOVER_ENTER: if (!mDownDetected && mAccessibilityManager.isTouchExplorationEnabled()) { - mVibrator.vibrate( - Process.myUid(), - getContext().getOpPackageName(), - UdfpsController.EFFECT_CLICK, - "lock-icon-down", - TOUCH_VIBRATION_ATTRIBUTES); + vibrateOnTouchExploration(); } // The pointer that causes ACTION_DOWN is always at index 0. @@ -696,13 +693,8 @@ public class LockIconViewController extends ViewController impleme mOnGestureDetectedRunnable.run(); } - // play device entry haptic (same as biometric success haptic) - mVibrator.vibrate( - Process.myUid(), - getContext().getOpPackageName(), - UdfpsController.EFFECT_CLICK, - "lock-screen-lock-icon-longpress", - TOUCH_VIBRATION_ATTRIBUTES); + // play device entry haptic (consistent with UDFPS controller longpress) + vibrateOnLongPress(); mKeyguardViewController.showPrimaryBouncer(/* scrim */ true); } @@ -750,6 +742,37 @@ public class LockIconViewController extends ViewController impleme }); } + @VisibleForTesting + void vibrateOnTouchExploration() { + if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) { + mVibrator.performHapticFeedback( + mView, + HapticFeedbackConstants.CONTEXT_CLICK + ); + } else { + mVibrator.vibrate( + Process.myUid(), + getContext().getOpPackageName(), + UdfpsController.EFFECT_CLICK, + "lock-icon-down", + TOUCH_VIBRATION_ATTRIBUTES); + } + } + + @VisibleForTesting + void vibrateOnLongPress() { + if (mFeatureFlags.isEnabled(ONE_WAY_HAPTICS_API_MIGRATION)) { + mVibrator.performHapticFeedback(mView, UdfpsController.LONG_PRESS); + } else { + mVibrator.vibrate( + Process.myUid(), + getContext().getOpPackageName(), + UdfpsController.EFFECT_CLICK, + "lock-screen-lock-icon-longpress", + TOUCH_VIBRATION_ATTRIBUTES); + } + } + private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { @Override public void onAllAuthenticatorsRegistered(@BiometricAuthenticator.Modality int modality) { diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java index ed6a891a6094c..45021ba1b3003 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java @@ -20,7 +20,9 @@ import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRIN import static com.android.keyguard.LockIconView.ICON_LOCK; import static com.android.keyguard.LockIconView.ICON_UNLOCK; +import static com.android.systemui.flags.Flags.ONE_WAY_HAPTICS_API_MIGRATION; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.eq; @@ -33,11 +35,13 @@ import android.hardware.biometrics.BiometricSourceType; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.Pair; +import android.view.HapticFeedbackConstants; import android.view.View; import androidx.test.filters.SmallTest; import com.android.settingslib.udfps.UdfpsOverlayParams; +import com.android.systemui.biometrics.UdfpsController; import com.android.systemui.doze.util.BurnInHelperKt; import org.junit.Test; @@ -339,4 +343,59 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest { // THEN the lock icon is shown verify(mLockIconView).setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); } + + @Test + public void playHaptic_onTouchExploration_NoOneWayHaptics_usesVibrate() { + mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, false); + + // WHEN request to vibrate on touch exploration + mUnderTest.vibrateOnTouchExploration(); + + // THEN vibrates + verify(mVibrator).vibrate( + anyInt(), + any(), + eq(UdfpsController.EFFECT_CLICK), + eq("lock-icon-down"), + any()); + } + + @Test + public void playHaptic_onTouchExploration_withOneWayHaptics_performHapticFeedback() { + mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true); + + // WHEN request to vibrate on touch exploration + mUnderTest.vibrateOnTouchExploration(); + + // THEN performHapticFeedback is used + verify(mVibrator).performHapticFeedback(any(), eq(HapticFeedbackConstants.CONTEXT_CLICK)); + } + + @Test + public void playHaptic_onLongPress_NoOneWayHaptics_usesVibrate() { + mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, false); + + // WHEN request to vibrate on long press + mUnderTest.vibrateOnLongPress(); + + // THEN uses vibrate + verify(mVibrator).vibrate( + anyInt(), + any(), + eq(UdfpsController.EFFECT_CLICK), + eq("lock-screen-lock-icon-longpress"), + any()); + } + + @Test + public void playHaptic_onLongPress_withOneWayHaptics_performHapticFeedback() { + mFeatureFlags.set(ONE_WAY_HAPTICS_API_MIGRATION, true); + + // WHEN request to vibrate on long press + mUnderTest.vibrateOnLongPress(); + + // THEN uses perform haptic feedback + verify(mVibrator).performHapticFeedback(any(), eq(UdfpsController.LONG_PRESS)); + + } }