summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java101
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java2
5 files changed, 102 insertions, 21 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index b4c6321fe191..7adc147784d7 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1359,7 +1359,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:AOD_INTERRUPT_END");
}
- mAuthController.onCancelAodInterrupt();
+ mAuthController.onCancelUdfps();
mIsUdfpsRunningWhileDozing = false;
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index ed8f32f31035..0c7b55d6ecbb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -309,18 +309,14 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
/**
- * Cancel a fingerprint scan.
- *
- * The sensor that triggers an AOD interrupt for fingerprint doesn't give
- * ACTION_UP/ACTION_CANCEL events, so the scan needs to be cancelled manually. This should be
- * called when authentication either succeeds or fails. Failing to cancel the scan will leave
- * the screen in high brightness mode.
+ * Cancel a fingerprint scan manually. This will get rid of the white circle on the udfps
+ * sensor area even if the user hasn't explicitly lifted their finger yet.
*/
- public void onCancelAodInterrupt() {
+ public void onCancelUdfps() {
if (mUdfpsController == null) {
return;
}
- mUdfpsController.onCancelAodInterrupt();
+ mUdfpsController.onCancelUdfps();
}
private void sendResultAndCleanUp(@DismissedReason int reason,
@@ -499,6 +495,8 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
if (DEBUG) Log.d(TAG, "onBiometricError, hard error: " + errorMessage);
mCurrentDialog.onError(errorMessage);
}
+
+ onCancelUdfps();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index aa818bfdadeb..9239a8ade615 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
@@ -35,15 +36,23 @@ import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback;
+import android.media.AudioAttributes;
+import android.os.Handler;
+import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
+import android.os.VibrationEffect;
+import android.os.Vibrator;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.VelocityTracker;
+import android.view.View;
import android.view.WindowManager;
import com.android.internal.annotations.VisibleForTesting;
@@ -94,7 +103,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
@NonNull private final DumpManager mDumpManager;
@NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
@NonNull private final KeyguardViewMediator mKeyguardViewMediator;
- @NonNull private FalsingManager mFalsingManager;
+ @NonNull private final Vibrator mVibrator;
+ @NonNull private final Handler mMainHandler;
+ @NonNull private final FalsingManager mFalsingManager;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -118,6 +129,27 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
private boolean mIsAodInterruptActive;
@Nullable private Runnable mCancelAodTimeoutAction;
+ private static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
+ new AudioAttributes.Builder()
+ .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
+ .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
+ .build();
+
+ 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);
+ private final VibrationEffect mEffectHeavy =
+ VibrationEffect.get(VibrationEffect.EFFECT_HEAVY_CLICK);
+ private final Runnable mAcquiredVibration = new Runnable() {
+ @Override
+ public void run() {
+ String effect = Settings.Global.getString(mContext.getContentResolver(),
+ "udfps_acquired_type");
+ mVibrator.vibrate(getVibration(effect, mEffectTick), VIBRATION_SONIFICATION_ATTRIBUTES);
+ }
+ };
+
/**
* Keeps track of state within a single FingerprintService request. Note that this state
* persists across configuration changes, etc, since it is considered a single request.
@@ -227,7 +259,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
};
@SuppressLint("ClickableViewAccessibility")
- private final UdfpsView.OnTouchListener mOnTouchListener = (view, event) -> {
+ private final UdfpsView.OnTouchListener mOnTouchListener = this::onTouch;
+
+ private boolean onTouch(View view, MotionEvent event) {
UdfpsView udfpsView = (UdfpsView) view;
final boolean isFingerDown = udfpsView.isIlluminationRequested();
boolean handled = false;
@@ -251,6 +285,27 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
// data for many other pointers because of multi-touch support.
mActivePointerId = event.getPointerId(0);
mVelocityTracker.addMovement(event);
+
+ // TODO: (b/185124905) these settings are for ux testing purposes and should
+ // be removed (or cached) before going into production
+ 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);
+ }
+
+ 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;
}
break;
@@ -307,7 +362,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
// Do nothing.
}
return handled;
- };
+ }
@Inject
public UdfpsController(@NonNull Context context,
@@ -324,6 +379,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
@NonNull KeyguardViewMediator keyguardViewMediator,
@NonNull FalsingManager falsingManager) {
mContext = context;
+ // TODO (b/185124905): inject main handler and vibrator once done prototyping
+ mMainHandler = new Handler(Looper.getMainLooper());
+ mVibrator = context.getSystemService(Vibrator.class);
mInflater = inflater;
// The fingerprint manager is queried for UDFPS before this class is constructed, so the
// fingerprint manager should never be null.
@@ -559,19 +617,25 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
// Since the sensor that triggers the AOD interrupt doesn't provide ACTION_UP/ACTION_CANCEL,
// we need to be careful about not letting the screen accidentally remain in high brightness
// mode. As a mitigation, queue a call to cancel the fingerprint scan.
- mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelAodInterrupt,
+ mCancelAodTimeoutAction = mFgExecutor.executeDelayed(this::onCancelUdfps,
AOD_INTERRUPT_TIMEOUT_MILLIS);
// using a hard-coded value for major and minor until it is available from the sensor
onFingerDown(screenX, screenY, minor, major);
}
/**
- * Cancel fingerprint scan.
+ * Cancel updfs scan affordances - ability to hide the HbmSurfaceView (white circle) before
+ * user explicitly lifts their finger. Generally, this should be called whenever udfps fails
+ * or errors.
*
- * This is intended to be called after the fingerprint scan triggered by the AOD interrupt
- * either succeeds or fails.
+ * The sensor that triggers an AOD fingerprint interrupt (see onAodInterrupt) doesn't give
+ * ACTION_UP/ACTION_CANCEL events, so and AOD interrupt scan needs to be cancelled manually.
+ * This should be called when authentication either succeeds or fails. Failing to cancel the
+ * scan will leave the screen in high brightness mode and will show the HbmSurfaceView until
+ * the user lifts their finger.
*/
- void onCancelAodInterrupt() {
+ void onCancelUdfps() {
+ onFingerUp();
if (!mIsAodInterruptActive) {
return;
}
@@ -580,7 +644,6 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
mCancelAodTimeoutAction = null;
}
mIsAodInterruptActive = false;
- onFingerUp();
}
// This method can be called from the UI thread.
@@ -598,6 +661,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
// This method can be called from the UI thread.
private void onFingerUp() {
+ mMainHandler.removeCallbacks(mAcquiredVibration);
if (mView == null) {
Log.w(TAG, "Null view in onFingerUp");
return;
@@ -617,4 +681,23 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
// Do nothing. This method can be implemented for devices that require the high-brightness
// mode for fingerprint illumination.
}
+
+ private VibrationEffect getVibration(String effect, VibrationEffect defaultEffect) {
+ if (TextUtils.isEmpty(effect)) {
+ return defaultEffect;
+ }
+
+ switch (effect.toLowerCase()) {
+ case "click":
+ return mEffectClick;
+ case "heavy":
+ return mEffectHeavy;
+ case "texture_tick":
+ return mEffectTextureTick;
+ case "tick":
+ return mEffectTick;
+ default:
+ return defaultEffect;
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index d544f7378f8a..42af366ad8fa 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -537,7 +537,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
authCallback.onAuthenticationFailed();
// THEN aod interrupt is cancelled
- verify(mAuthController).onCancelAodInterrupt();
+ verify(mAuthController).onCancelUdfps();
}
@Test
@@ -557,7 +557,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
authCallback.onAuthenticationError(0, "");
// THEN aod interrupt is cancelled
- verify(mAuthController).onCancelAodInterrupt();
+ verify(mAuthController).onCancelUdfps();
}
@Test
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 bbd3ce89b997..0aa182fb1e81 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -259,7 +259,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
mFgExecutor.runAllReady();
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
// WHEN it is cancelled
- mUdfpsController.onCancelAodInterrupt();
+ mUdfpsController.onCancelUdfps();
// THEN the illumination is hidden
verify(mUdfpsView).stopIllumination();
}