Loading packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +36 −13 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -613,12 +615,7 @@ public class LockIconViewController extends ViewController<LockIconView> 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. Loading Loading @@ -699,13 +696,8 @@ public class LockIconViewController extends ViewController<LockIconView> 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); } Loading Loading @@ -753,6 +745,37 @@ public class LockIconViewController extends ViewController<LockIconView> 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) { Loading packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java +59 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)); } } Loading
packages/SystemUI/src/com/android/keyguard/LockIconViewController.java +36 −13 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -613,12 +615,7 @@ public class LockIconViewController extends ViewController<LockIconView> 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. Loading Loading @@ -699,13 +696,8 @@ public class LockIconViewController extends ViewController<LockIconView> 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); } Loading Loading @@ -753,6 +745,37 @@ public class LockIconViewController extends ViewController<LockIconView> 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) { Loading
packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java +59 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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)); } }