diff options
8 files changed, 149 insertions, 18 deletions
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 3bc1c8053db3..b3fca366ea1e 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -183,7 +183,9 @@ <color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 --> <!-- UDFPS colors --> - <color name="udfps_enroll_icon">#000000</color> <!-- 100% black --> + <color name="udfps_enroll_icon">#000000</color> <!-- 100% black --> + <color name="udfps_moving_target_fill">#cc4285f4</color> <!-- 80% blue --> + <color name="udfps_moving_target_stroke">#ff669DF6</color> <!-- 100% blue --> <!-- Logout button --> <color name="logout_button_bg_color">#ccffffff</color> diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java index a02900328ae7..e99819102e94 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java @@ -17,6 +17,7 @@ package com.android.systemui.biometrics; import android.content.Context; +import android.graphics.Rect; import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.view.View; @@ -46,12 +47,17 @@ public abstract class UdfpsAnimation extends Drawable { } public void onSensorRectUpdated(@NonNull RectF sensorRect) { - int margin = (int) (sensorRect.bottom - sensorRect.top) / 5; - mFingerprintDrawable.setBounds( - (int) sensorRect.left + margin, + final int margin = (int) sensorRect.height() / 5; + + final Rect bounds = new Rect((int) sensorRect.left + margin, (int) sensorRect.top + margin, (int) sensorRect.right - margin, (int) sensorRect.bottom - margin); + updateFingerprintIconBounds(bounds); + } + + protected void updateFingerprintIconBounds(@NonNull Rect bounds) { + mFingerprintDrawable.setBounds(bounds); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java index 28b57195c5d4..015a598e972b 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationEnroll.java @@ -22,13 +22,14 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.Rect; import android.graphics.RectF; -import android.util.Log; +import android.graphics.drawable.Drawable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import com.android.settingslib.Utils; import com.android.systemui.R; /** @@ -40,9 +41,13 @@ public class UdfpsAnimationEnroll extends UdfpsAnimation { private static final float SHADOW_RADIUS = 5.f; private static final float PROGRESS_BAR_RADIUS = 140.f; - @Nullable private RectF mSensorRect; + @NonNull private final Drawable mMovingTargetFpIcon; @NonNull private final Paint mSensorPaint; - private final int mNotificationShadeColor; + @NonNull private final Paint mBlueFill; + @NonNull private final Paint mBlueStroke;; + + @Nullable private RectF mSensorRect; + @Nullable private UdfpsEnrollHelper mEnrollHelper; UdfpsAnimationEnroll(@NonNull Context context) { super(context); @@ -53,8 +58,24 @@ public class UdfpsAnimationEnroll extends UdfpsAnimation { mSensorPaint.setShadowLayer(SHADOW_RADIUS, 0, 0, Color.BLACK); mSensorPaint.setStyle(Paint.Style.FILL); - mNotificationShadeColor = Utils.getColorAttr(context, - android.R.attr.colorBackgroundFloating).getDefaultColor(); + mBlueFill = new Paint(0 /* flags */); + mBlueFill.setAntiAlias(true); + mBlueFill.setColor(context.getColor(R.color.udfps_moving_target_fill)); + mBlueFill.setStyle(Paint.Style.FILL); + + mBlueStroke = new Paint(0 /* flags */); + mBlueStroke.setAntiAlias(true); + mBlueStroke.setColor(context.getColor(R.color.udfps_moving_target_stroke)); + mBlueStroke.setStyle(Paint.Style.STROKE); + mBlueStroke.setStrokeWidth(12); + + mMovingTargetFpIcon = context.getResources().getDrawable(R.drawable.ic_fingerprint, null); + mMovingTargetFpIcon.setTint(Color.WHITE); + mMovingTargetFpIcon.mutate(); + } + + void setEnrollHelper(@NonNull UdfpsEnrollHelper helper) { + mEnrollHelper = helper; } @Override @@ -74,6 +95,12 @@ public class UdfpsAnimationEnroll extends UdfpsAnimation { } @Override + protected void updateFingerprintIconBounds(@NonNull Rect bounds) { + super.updateFingerprintIconBounds(bounds); + mMovingTargetFpIcon.setBounds(bounds); + } + + @Override public void draw(@NonNull Canvas canvas) { if (isIlluminationShowing()) { return; @@ -87,6 +114,24 @@ public class UdfpsAnimationEnroll extends UdfpsAnimation { } } mFingerprintDrawable.draw(canvas); + + // Draw moving target + if (mEnrollHelper.isCenterEnrollmentComplete()) { + mFingerprintDrawable.setAlpha(64); + + canvas.save(); + final PointF point = mEnrollHelper.getNextGuidedEnrollmentPoint(); + canvas.translate(point.x, point.y); + if (mSensorRect != null) { + canvas.drawOval(mSensorRect, mBlueFill); + canvas.drawOval(mSensorRect, mBlueStroke); + } + + mMovingTargetFpIcon.draw(canvas); + canvas.restore(); + } else { + mFingerprintDrawable.setAlpha(255); + } } @Override diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java index 6666c8dda527..43ecf6778022 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Canvas; +import android.graphics.PointF; import android.graphics.RectF; import android.util.AttributeSet; import android.widget.FrameLayout; @@ -142,4 +143,14 @@ public abstract class UdfpsAnimationView extends FrameLayout implements DozeRece } return getUdfpsAnimation().getPaddingY(); } + + /** + * @return the amount of translation needed if the view currently requires the user to touch + * somewhere other than the exact center of the sensor. For example, this can happen + * during guided enrollment. + */ + @NonNull + PointF getTouchTranslation() { + return new PointF(0, 0); + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewEnroll.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewEnroll.java index 19e774937e20..543df33dd5d7 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewEnroll.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewEnroll.java @@ -19,6 +19,7 @@ package com.android.systemui.biometrics; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; +import android.graphics.PointF; import android.util.AttributeSet; import android.util.Log; import android.view.View; @@ -33,7 +34,7 @@ public class UdfpsAnimationViewEnroll extends UdfpsAnimationView private static final String TAG = "UdfpsAnimationViewEnroll"; - @NonNull private UdfpsAnimation mUdfpsAnimation; + @NonNull private UdfpsAnimationEnroll mUdfpsAnimation; @NonNull private UdfpsProgressBar mProgressBar; @Nullable private UdfpsEnrollHelper mEnrollHelper; @@ -50,6 +51,7 @@ public class UdfpsAnimationViewEnroll extends UdfpsAnimationView public void setEnrollHelper(@NonNull UdfpsEnrollHelper helper) { mEnrollHelper = helper; + mUdfpsAnimation.setEnrollHelper(helper); } @Override @@ -81,4 +83,14 @@ public class UdfpsAnimationViewEnroll extends UdfpsAnimationView mProgressBar.setProgress(interpolatedProgress, true); } + + @NonNull + @Override + PointF getTouchTranslation() { + if (!mEnrollHelper.isCenterEnrollmentComplete()) { + return new PointF(0, 0); + } else { + return mEnrollHelper.getNextGuidedEnrollmentPoint(); + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index be27b24c90ac..a09d760bbdc4 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -97,7 +97,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback { public void showUdfpsOverlay(int sensorId, int reason) { if (reason == IUdfpsOverlayController.REASON_ENROLL_FIND_SENSOR || reason == IUdfpsOverlayController.REASON_ENROLL_ENROLLING) { - mEnrollHelper = new UdfpsEnrollHelper(reason); + mEnrollHelper = new UdfpsEnrollHelper(mContext, reason); } else { mEnrollHelper = null; } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java index 942fa7aae0bc..14eca1b1cb2c 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollHelper.java @@ -18,7 +18,13 @@ package com.android.systemui.biometrics; import android.annotation.NonNull; import android.annotation.Nullable; +import android.content.Context; +import android.graphics.PointF; import android.hardware.fingerprint.IUdfpsOverlayController; +import android.util.TypedValue; + +import java.util.ArrayList; +import java.util.List; /** * Helps keep track of enrollment state and animates the progress bar accordingly. @@ -26,20 +32,48 @@ import android.hardware.fingerprint.IUdfpsOverlayController; public class UdfpsEnrollHelper { private static final String TAG = "UdfpsEnrollHelper"; + // Enroll with two center touches before going to guided enrollment + private static final int NUM_CENTER_TOUCHES = 2; + interface Listener { void onEnrollmentProgress(int remaining, int totalSteps); } // IUdfpsOverlayController reason private final int mEnrollReason; + private final List<PointF> mGuidedEnrollmentPoints; private int mTotalSteps = -1; - private int mCurrentProgress = 0; + private int mRemainingSteps = -1; + + // Note that this is actually not equal to "mTotalSteps - mRemainingSteps", because the + // interface makes no promises about monotonically increasing by one each time. + private int mLocationsEnrolled = 0; @Nullable Listener mListener; - public UdfpsEnrollHelper(int reason) { + public UdfpsEnrollHelper(@NonNull Context context, int reason) { mEnrollReason = reason; + mGuidedEnrollmentPoints = new ArrayList<>(); + + // Number of pixels per mm + float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1, + context.getResources().getDisplayMetrics()); + + mGuidedEnrollmentPoints.add(new PointF( 2.00f * px, 0.00f * px)); + mGuidedEnrollmentPoints.add(new PointF( 0.87f * px, -2.70f * px)); + mGuidedEnrollmentPoints.add(new PointF(-1.80f * px, -1.31f * px)); + mGuidedEnrollmentPoints.add(new PointF(-1.80f * px, 1.31f * px)); + mGuidedEnrollmentPoints.add(new PointF( 0.88f * px, 2.70f * px)); + mGuidedEnrollmentPoints.add(new PointF( 3.94f * px, -1.06f * px)); + mGuidedEnrollmentPoints.add(new PointF( 2.90f * px, -4.14f * px)); + mGuidedEnrollmentPoints.add(new PointF(-0.52f * px, -5.95f * px)); + mGuidedEnrollmentPoints.add(new PointF(-3.33f * px, -3.33f * px)); + mGuidedEnrollmentPoints.add(new PointF(-3.99f * px, -0.35f * px)); + mGuidedEnrollmentPoints.add(new PointF(-3.62f * px, 2.54f * px)); + mGuidedEnrollmentPoints.add(new PointF(-1.49f * px, 5.57f * px)); + mGuidedEnrollmentPoints.add(new PointF( 2.29f * px, 4.92f * px)); + mGuidedEnrollmentPoints.add(new PointF( 3.82f * px, 1.78f * px)); } boolean shouldShowProgressBar() { @@ -51,6 +85,12 @@ public class UdfpsEnrollHelper { mTotalSteps = remaining; } + if (remaining != mRemainingSteps) { + mLocationsEnrolled++; + } + + mRemainingSteps = remaining; + if (mListener != null) { mListener.onEnrollmentProgress(remaining, mTotalSteps); } @@ -67,8 +107,21 @@ public class UdfpsEnrollHelper { // bar can be updated. If enrollment has not started yet, the progress bar will be empty // anyway. if (mTotalSteps != -1) { - final int remainingSteps = mTotalSteps - mCurrentProgress; - mListener.onEnrollmentProgress(remainingSteps, mTotalSteps); + mListener.onEnrollmentProgress(mRemainingSteps, mTotalSteps); + } + } + + boolean isCenterEnrollmentComplete() { + if (mTotalSteps == -1 || mRemainingSteps == -1) { + return false; } + final int stepsEnrolled = mTotalSteps - mRemainingSteps; + return stepsEnrolled >= NUM_CENTER_TOUCHES; + } + + @NonNull + PointF getNextGuidedEnrollmentPoint() { + final int index = mLocationsEnrolled - NUM_CENTER_TOUCHES; + return mGuidedEnrollmentPoints.get(index % mGuidedEnrollmentPoints.size()); } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java index cd849e63ba9c..75a362131de1 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java @@ -27,6 +27,7 @@ import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; +import android.graphics.PointF; import android.graphics.RectF; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.text.TextUtils; @@ -180,8 +181,9 @@ public class UdfpsView extends FrameLayout implements DozeReceiver, UdfpsIllumin boolean isValidTouch(float x, float y, float pressure) { // The X and Y coordinates of the sensor's center. - final float cx = mSensorRect.centerX(); - final float cy = mSensorRect.centerY(); + final PointF translation = mAnimationView.getTouchTranslation(); + final float cx = mSensorRect.centerX() + translation.x; + final float cy = mSensorRect.centerY() + translation.y; // Radii along the X and Y axes. final float rx = (mSensorRect.right - mSensorRect.left) / 2.0f; final float ry = (mSensorRect.bottom - mSensorRect.top) / 2.0f; |