Loading packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +31 −21 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading @@ -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 = Loading @@ -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); Loading Loading @@ -389,14 +394,16 @@ 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(); if (mVibrator != null) { final ContentResolver contentResolver = mContext.getContentResolver(); int startEnabled = Settings.Global.getInt(contentResolver, "udfps_start", 0); "udfps_start", 1); if (startEnabled > 0) { String startEffectSetting = Settings.Global.getString( contentResolver, "udfps_start_type"); mVibrator.vibrate(getVibration(startEffectSetting, mEffectClick), VIBRATION_SONIFICATION_ATTRIBUTES); mVibrator.vibrate(getVibration(startEffectSetting, mEffectClick), VIBRATION_SONIFICATION_ATTRIBUTES); } int acquiredEnabled = Settings.Global.getInt(contentResolver, Loading @@ -407,6 +414,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback { mMainHandler.removeCallbacks(mAcquiredVibration); mMainHandler.postDelayed(mAcquiredVibration, delay); } } handled = true; } else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) { Log.v(TAG, "onTouch | finger move: " + touchInfo); Loading Loading @@ -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. Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +30 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -114,6 +115,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private AccessibilityManager mAccessibilityManager; @Mock private ScreenLifecycle mScreenLifecycle; @Mock private Vibrator mVibrator; private FakeExecutor mFgExecutor; Loading Loading @@ -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()); Loading Loading @@ -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); } } Loading
packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +31 −21 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) Loading @@ -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 = Loading @@ -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); Loading Loading @@ -389,14 +394,16 @@ 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(); if (mVibrator != null) { final ContentResolver contentResolver = mContext.getContentResolver(); int startEnabled = Settings.Global.getInt(contentResolver, "udfps_start", 0); "udfps_start", 1); if (startEnabled > 0) { String startEffectSetting = Settings.Global.getString( contentResolver, "udfps_start_type"); mVibrator.vibrate(getVibration(startEffectSetting, mEffectClick), VIBRATION_SONIFICATION_ATTRIBUTES); mVibrator.vibrate(getVibration(startEffectSetting, mEffectClick), VIBRATION_SONIFICATION_ATTRIBUTES); } int acquiredEnabled = Settings.Global.getInt(contentResolver, Loading @@ -407,6 +414,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback { mMainHandler.removeCallbacks(mAcquiredVibration); mMainHandler.postDelayed(mAcquiredVibration, delay); } } handled = true; } else if (sinceLastLog >= MIN_TOUCH_LOG_INTERVAL) { Log.v(TAG, "onTouch | finger move: " + touchInfo); Loading Loading @@ -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. Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java +30 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -114,6 +115,8 @@ public class UdfpsControllerTest extends SysuiTestCase { private AccessibilityManager mAccessibilityManager; @Mock private ScreenLifecycle mScreenLifecycle; @Mock private Vibrator mVibrator; private FakeExecutor mFgExecutor; Loading Loading @@ -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()); Loading Loading @@ -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); } }