diff options
| -rw-r--r-- | packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java | 52 | ||||
| -rw-r--r-- | packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java | 31 |
2 files changed, 61 insertions, 22 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 5f27400741a9..5a50f0eed833 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -105,7 +105,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback { @NonNull private final DumpManager mDumpManager; @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; @NonNull private final KeyguardViewMediator mKeyguardViewMediator; - @NonNull private final Vibrator mVibrator; + @Nullable private final Vibrator mVibrator; @NonNull private final Handler mMainHandler; @NonNull private final FalsingManager mFalsingManager; @NonNull private final PowerManager mPowerManager; @@ -135,7 +135,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback { private boolean mScreenOn; private Runnable mAodInterruptRunnable; - private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = + @VisibleForTesting + static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION) @@ -144,7 +145,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback { private final VibrationEffect mEffectTick = VibrationEffect.get(VibrationEffect.EFFECT_TICK); private final VibrationEffect mEffectTextureTick = VibrationEffect.get(VibrationEffect.EFFECT_TEXTURE_TICK); - private final VibrationEffect mEffectClick = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); + @VisibleForTesting + final VibrationEffect mEffectClick = VibrationEffect.get(VibrationEffect.EFFECT_CLICK); private final VibrationEffect mEffectHeavy = VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK); private final VibrationEffect mDoubleClick = @@ -152,6 +154,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback { private final Runnable mAcquiredVibration = new Runnable() { @Override public void run() { + if (mVibrator == null) { + return; + } String effect = Settings.Global.getString(mContext.getContentResolver(), "udfps_acquired_type"); mVibrator.vibrate(getVibration(effect, mEffectTick), VIBRATION_SONIFICATION_ATTRIBUTES); @@ -389,24 +394,28 @@ public class UdfpsController implements DozeReceiver, HbmCallback { PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0); // TODO: this should eventually be removed after ux testing - final ContentResolver contentResolver = mContext.getContentResolver(); - int startEnabled = Settings.Global.getInt(contentResolver, - "udfps_start", 0); - if (startEnabled > 0) { - String startEffectSetting = Settings.Global.getString( - contentResolver, "udfps_start_type"); - mVibrator.vibrate(getVibration(startEffectSetting, mEffectClick), - VIBRATION_SONIFICATION_ATTRIBUTES); + if (mVibrator != null) { + final ContentResolver contentResolver = + mContext.getContentResolver(); + int startEnabled = Settings.Global.getInt(contentResolver, + "udfps_start", 1); + if (startEnabled > 0) { + String startEffectSetting = Settings.Global.getString( + contentResolver, "udfps_start_type"); + mVibrator.vibrate(getVibration(startEffectSetting, + mEffectClick), VIBRATION_SONIFICATION_ATTRIBUTES); + } + + int acquiredEnabled = Settings.Global.getInt(contentResolver, + "udfps_acquired", 0); + if (acquiredEnabled > 0) { + int delay = Settings.Global.getInt(contentResolver, + "udfps_acquired_delay", 500); + mMainHandler.removeCallbacks(mAcquiredVibration); + mMainHandler.postDelayed(mAcquiredVibration, delay); + } } - int acquiredEnabled = Settings.Global.getInt(contentResolver, - "udfps_acquired", 0); - if (acquiredEnabled > 0) { - int delay = Settings.Global.getInt(contentResolver, - "udfps_acquired_delay", 500); - mMainHandler.removeCallbacks(mAcquiredVibration); - mMainHandler.postDelayed(mAcquiredVibration, delay); - } handled = true; } else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) { Log.v(TAG, "onTouch | finger move: " + touchInfo); @@ -456,11 +465,12 @@ public class UdfpsController implements DozeReceiver, HbmCallback { @NonNull FalsingManager falsingManager, @NonNull PowerManager powerManager, @NonNull AccessibilityManager accessibilityManager, - @NonNull ScreenLifecycle screenLifecycle) { + @NonNull ScreenLifecycle screenLifecycle, + @Nullable Vibrator vibrator) { mContext = context; // TODO (b/185124905): inject main handler and vibrator once done prototyping mMainHandler = new Handler(Looper.getMainLooper()); - mVibrator = context.getSystemService(Vibrator.class); + mVibrator = vibrator; mInflater = inflater; // The fingerprint manager is queried for UDFPS before this class is constructed, so the // fingerprint manager should never be null. diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java index 875696a08cf1..2530cfd70441 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java @@ -35,6 +35,7 @@ import android.hardware.fingerprint.IUdfpsOverlayController; import android.hardware.fingerprint.IUdfpsOverlayControllerCallback; import android.os.PowerManager; import android.os.RemoteException; +import android.os.Vibrator; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.LayoutInflater; @@ -114,6 +115,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private AccessibilityManager mAccessibilityManager; @Mock private ScreenLifecycle mScreenLifecycle; + @Mock + private Vibrator mVibrator; private FakeExecutor mFgExecutor; @@ -170,7 +173,8 @@ public class UdfpsControllerTest extends SysuiTestCase { mFalsingManager, mPowerManager, mAccessibilityManager, - mScreenLifecycle); + mScreenLifecycle, + mVibrator); verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture()); mOverlayController = mOverlayCaptor.getValue(); verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture()); @@ -302,4 +306,29 @@ public class UdfpsControllerTest extends SysuiTestCase { // THEN no illumination because screen is off verify(mUdfpsView, never()).startIllumination(any()); } + + @Test + public void playHapticOnTouchUdfpsArea() throws RemoteException { + // Configure UdfpsView to accept the ACTION_DOWN event + when(mUdfpsView.isIlluminationRequested()).thenReturn(false); + when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true); + + // GIVEN that the overlay is showing + mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID, + IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD, mUdfpsOverlayControllerCallback); + mFgExecutor.runAllReady(); + + // WHEN ACTION_DOWN is received + verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture()); + MotionEvent downEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, downEvent); + downEvent.recycle(); + MotionEvent moveEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE, 0, 0, 0); + mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent); + moveEvent.recycle(); + + // THEN click haptic is played + verify(mVibrator).vibrate(mUdfpsController.mEffectClick, + UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES); + } } |