Plumb UDFPS overlay "show reason" from FingerprintService to SysUI
Enables SysUI to draw enroll/auth-specific affordances If the UI diverges, we can consider enroll or auth specific UdfpsView subclasses(?) but currently enrollment just shows an extra circle. Fixes: 177275693 Test: atest com.android.systemui.biometrics Change-Id: I5b2aaf00c55279a81348ec7a5dc387b6e62751c0
This commit is contained in:
@@ -20,8 +20,12 @@ package android.hardware.fingerprint;
|
||||
* @hide
|
||||
*/
|
||||
oneway interface IUdfpsOverlayController {
|
||||
const int REASON_UNKNOWN = 0;
|
||||
const int REASON_ENROLL = 1;
|
||||
const int REASON_AUTH = 2;
|
||||
|
||||
// Shows the overlay.
|
||||
void showUdfpsOverlay(int sensorId);
|
||||
void showUdfpsOverlay(int sensorId, int reason);
|
||||
|
||||
// Hides the overlay.
|
||||
void hideUdfpsOverlay(int sensorId);
|
||||
|
||||
@@ -77,6 +77,9 @@
|
||||
<color name="biometric_dialog_accent">#ff80cbc4</color> <!-- light teal -->
|
||||
<color name="biometric_dialog_error">#fff28b82</color> <!-- red 300 -->
|
||||
|
||||
<!-- UDFPS colors -->
|
||||
<color name="udfps_enroll_icon">#ffffff</color> <!-- 100% white -->
|
||||
|
||||
<color name="GM2_green_500">#FF41Af6A</color>
|
||||
<color name="GM2_blue_500">#5195EA</color>
|
||||
<color name="GM2_red_500">#E25142</color>
|
||||
|
||||
@@ -178,6 +178,9 @@
|
||||
<color name="biometric_dialog_accent">#ff008577</color> <!-- dark teal -->
|
||||
<color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
|
||||
|
||||
<!-- UDFPS colors -->
|
||||
<color name="udfps_enroll_icon">#000000</color> <!-- 100% black -->
|
||||
|
||||
<!-- Logout button -->
|
||||
<color name="logout_button_bg_color">#ccffffff</color>
|
||||
|
||||
|
||||
@@ -546,6 +546,12 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
protected void onConfigurationChanged(Configuration newConfig) {
|
||||
super.onConfigurationChanged(newConfig);
|
||||
|
||||
// UdfpsController is not BiometricPrompt-specific. It can be active for keyguard or
|
||||
// enrollment.
|
||||
if (mUdfpsController != null) {
|
||||
mUdfpsController.onConfigurationChanged();
|
||||
}
|
||||
|
||||
// Save the state of the current dialog (buttons showing, etc)
|
||||
if (mCurrentDialog != null) {
|
||||
final Bundle savedState = new Bundle();
|
||||
@@ -567,10 +573,6 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
|
||||
promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
|
||||
}
|
||||
|
||||
if (mUdfpsController != null) {
|
||||
mUdfpsController.onConfigurationChanged();
|
||||
}
|
||||
|
||||
showDialog(mCurrentDialogArgs, true /* skipAnimation */, savedState);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,8 @@ class UdfpsController implements DozeReceiver {
|
||||
private boolean mIsOverlayShowing;
|
||||
// Indicates whether the overlay has been requested.
|
||||
private boolean mIsOverlayRequested;
|
||||
// Reason the overlay has been requested. See IUdfpsOverlayController for definitions.
|
||||
private int mRequestReason;
|
||||
|
||||
// The fingerprint AOD trigger doesn't provide an ACTION_UP/ACTION_CANCEL event to tell us when
|
||||
// to turn off high brightness mode. To get around this limitation, the state of the AOD
|
||||
@@ -118,13 +120,13 @@ class UdfpsController implements DozeReceiver {
|
||||
|
||||
public class UdfpsOverlayController extends IUdfpsOverlayController.Stub {
|
||||
@Override
|
||||
public void showUdfpsOverlay(int sensorId) {
|
||||
UdfpsController.this.setShowOverlay(true);
|
||||
public void showUdfpsOverlay(int sensorId, int reason) {
|
||||
UdfpsController.this.showOverlay(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideUdfpsOverlay(int sensorId) {
|
||||
UdfpsController.this.setShowOverlay(false);
|
||||
UdfpsController.this.hideOverlay();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -285,17 +287,27 @@ class UdfpsController implements DozeReceiver {
|
||||
return mView.getSensorRect();
|
||||
}
|
||||
|
||||
private void setShowOverlay(boolean show) {
|
||||
if (show == mIsOverlayRequested) {
|
||||
private void showOverlay(int reason) {
|
||||
if (mIsOverlayRequested) {
|
||||
return;
|
||||
}
|
||||
mIsOverlayRequested = show;
|
||||
mIsOverlayRequested = true;
|
||||
mRequestReason = reason;
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
private void hideOverlay() {
|
||||
if (!mIsOverlayRequested) {
|
||||
return;
|
||||
}
|
||||
mIsOverlayRequested = false;
|
||||
mRequestReason = IUdfpsOverlayController.REASON_UNKNOWN;
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
private void updateOverlay() {
|
||||
if (mIsOverlayRequested) {
|
||||
showUdfpsOverlay();
|
||||
showUdfpsOverlay(mRequestReason);
|
||||
} else {
|
||||
hideUdfpsOverlay();
|
||||
}
|
||||
@@ -323,11 +335,12 @@ class UdfpsController implements DozeReceiver {
|
||||
updateOverlay();
|
||||
}
|
||||
|
||||
private void showUdfpsOverlay() {
|
||||
private void showUdfpsOverlay(int reason) {
|
||||
mFgExecutor.execute(() -> {
|
||||
if (!mIsOverlayShowing) {
|
||||
try {
|
||||
Log.v(TAG, "showUdfpsOverlay | adding window");
|
||||
mView.setShowReason(reason);
|
||||
mWindowManager.addView(mView, computeLayoutParams());
|
||||
mIsOverlayShowing = true;
|
||||
mView.setOnTouchListener(mOnTouchListener);
|
||||
@@ -344,6 +357,7 @@ class UdfpsController implements DozeReceiver {
|
||||
mFgExecutor.execute(() -> {
|
||||
if (mIsOverlayShowing) {
|
||||
Log.v(TAG, "hideUdfpsOverlay | removing window");
|
||||
mView.setShowReason(IUdfpsOverlayController.REASON_UNKNOWN);
|
||||
mView.setOnTouchListener(null);
|
||||
// Reset the controller back to its starting state.
|
||||
onFingerUp();
|
||||
|
||||
@@ -21,6 +21,7 @@ import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
@@ -29,10 +30,12 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
|
||||
import android.hardware.fingerprint.IUdfpsOverlayController;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.util.MathUtils;
|
||||
import android.util.TypedValue;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
@@ -81,6 +84,7 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
private float mBurnInOffsetX;
|
||||
private float mBurnInOffsetY;
|
||||
|
||||
private int mShowReason;
|
||||
private boolean mShowScrimAndDot;
|
||||
private boolean mIsHbmSupported;
|
||||
@Nullable private String mDebugMessage;
|
||||
@@ -140,6 +144,13 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
mSensorProps = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param reason See {@link android.hardware.fingerprint.IUdfpsOverlayController}
|
||||
*/
|
||||
void setShowReason(int reason) {
|
||||
mShowReason = reason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dozeTimeTick() {
|
||||
updateAodPosition();
|
||||
@@ -208,14 +219,26 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
// is finished, mTouchableRegion will be used by mInsetsListener to compute the touch
|
||||
// insets.
|
||||
mSensorRect.roundOut(mTouchableRegion);
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
Log.v(TAG, "onAttachedToWindow");
|
||||
|
||||
// Retrieve the colors each time, since it depends on day/night mode
|
||||
final TypedValue tv = new TypedValue();
|
||||
mContext.getTheme().resolveAttribute(R.attr.wallpaperTextColor, tv, true);
|
||||
final int authIconColor = mContext.getResources()
|
||||
.getColor(tv.resourceId, mContext.getTheme());
|
||||
final int enrollIconColor = mContext.getColor(R.color.udfps_enroll_icon);
|
||||
|
||||
if (mShowReason == IUdfpsOverlayController.REASON_AUTH) {
|
||||
mFingerprintDrawable.setTint(authIconColor);
|
||||
} else if (mShowReason == IUdfpsOverlayController.REASON_ENROLL) {
|
||||
mFingerprintDrawable.setTint(enrollIconColor);
|
||||
}
|
||||
|
||||
getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsListener);
|
||||
}
|
||||
|
||||
@@ -246,6 +269,11 @@ public class UdfpsView extends View implements DozeReceiver,
|
||||
// draw dot (white circle)
|
||||
canvas.drawOval(mSensorRect, mSensorPaint);
|
||||
} else {
|
||||
final boolean isNightMode = (getResources().getConfiguration().uiMode
|
||||
& Configuration.UI_MODE_NIGHT_YES) != 0;
|
||||
if (mShowReason == IUdfpsOverlayController.REASON_ENROLL && !isNightMode) {
|
||||
canvas.drawOval(mSensorRect, mSensorPaint);
|
||||
}
|
||||
// draw fingerprint icon
|
||||
mFingerprintDrawable.draw(canvas);
|
||||
}
|
||||
|
||||
@@ -160,14 +160,16 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void showUdfpsOverlay_addsViewToWindow() throws RemoteException {
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
mFgExecutor.runAllReady();
|
||||
verify(mWindowManager).addView(eq(mUdfpsView), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hideUdfpsOverlay_removesViewFromWindow() throws RemoteException {
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
mOverlayController.hideUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mFgExecutor.runAllReady();
|
||||
verify(mWindowManager).removeView(eq(mUdfpsView));
|
||||
@@ -180,7 +182,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
when(mUdfpsView.isValidTouch(anyFloat(), anyFloat(), anyFloat())).thenReturn(true);
|
||||
|
||||
// GIVEN that the overlay is showing
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
mFgExecutor.runAllReady();
|
||||
// WHEN ACTION_DOWN is received
|
||||
verify(mUdfpsView).setOnTouchListener(mTouchListenerCaptor.capture());
|
||||
@@ -197,7 +200,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void aodInterrupt() throws RemoteException {
|
||||
// GIVEN that the overlay is showing
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
mFgExecutor.runAllReady();
|
||||
// WHEN fingerprint is requested because of AOD interrupt
|
||||
mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
|
||||
@@ -211,7 +215,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void cancelAodInterrupt() throws RemoteException {
|
||||
// GIVEN AOD interrupt
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
mFgExecutor.runAllReady();
|
||||
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
|
||||
// WHEN it is cancelled
|
||||
@@ -223,7 +228,8 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
@Test
|
||||
public void aodInterruptTimeout() throws RemoteException {
|
||||
// GIVEN AOD interrupt
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID);
|
||||
mOverlayController.showUdfpsOverlay(TEST_UDFPS_SENSOR_ID,
|
||||
IUdfpsOverlayController.REASON_AUTH);
|
||||
mFgExecutor.runAllReady();
|
||||
mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
|
||||
// WHEN it times out
|
||||
|
||||
@@ -62,13 +62,13 @@ public class UdfpsHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public static void showUdfpsOverlay(int sensorId,
|
||||
public static void showUdfpsOverlay(int sensorId, int reason,
|
||||
@Nullable IUdfpsOverlayController udfpsOverlayController) {
|
||||
if (udfpsOverlayController == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
udfpsOverlayController.showUdfpsOverlay(sensorId);
|
||||
udfpsOverlayController.showUdfpsOverlay(sensorId, reason);
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Remote exception when showing the UDFPS overlay", e);
|
||||
}
|
||||
|
||||
@@ -80,7 +80,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
mCancellationSignal = getFreshDaemon().authenticate(mSequentialId, mOperationId);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -69,7 +69,8 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> {
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
mCancellationSignal = getFreshDaemon().detectInteraction(mSequentialId);
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -94,7 +94,8 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps {
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_ENROLL,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
mCancellationSignal = getFreshDaemon().enroll(mSequentialId,
|
||||
HardwareAuthTokenUtils.toHardwareAuthToken(mHardwareAuthToken));
|
||||
|
||||
@@ -113,7 +113,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
// GroupId was never used. In fact, groupId is always the same as userId.
|
||||
getFreshDaemon().authenticate(mOperationId, getTargetUserId());
|
||||
|
||||
@@ -82,7 +82,8 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_AUTH,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
getFreshDaemon().authenticate(0 /* operationId */, getTargetUserId());
|
||||
} catch (RemoteException e) {
|
||||
|
||||
@@ -76,7 +76,8 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
|
||||
|
||||
@Override
|
||||
protected void startHalOperation() {
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), mUdfpsOverlayController);
|
||||
UdfpsHelper.showUdfpsOverlay(getSensorId(), IUdfpsOverlayController.REASON_ENROLL,
|
||||
mUdfpsOverlayController);
|
||||
try {
|
||||
// GroupId was never used. In fact, groupId is always the same as userId.
|
||||
getFreshDaemon().enroll(mHardwareAuthToken, getTargetUserId(), mTimeoutSec);
|
||||
|
||||
Reference in New Issue
Block a user