diff --git a/res/layout/udfps_enroll_enrolling.xml b/res/layout/udfps_enroll_enrolling.xml
new file mode 100644
index 00000000000..03b6528b32e
--- /dev/null
+++ b/res/layout/udfps_enroll_enrolling.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
diff --git a/res/layout/udfps_enroll_layout.xml b/res/layout/udfps_enroll_layout.xml
new file mode 100644
index 00000000000..51c788b3bae
--- /dev/null
+++ b/res/layout/udfps_enroll_layout.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
index f131e35457d..9b86e78eff9 100644
--- a/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/BiometricsEnrollEnrolling.java
@@ -16,6 +16,7 @@
package com.android.settings.biometrics;
+import android.annotation.Nullable;
import android.content.Intent;
import android.os.UserHandle;
import android.view.View;
@@ -33,6 +34,7 @@ public abstract class BiometricsEnrollEnrolling extends BiometricEnrollBase
private static final String TAG_SIDECAR = "sidecar";
+ @Nullable
protected BiometricEnrollSidecar mSidecar;
/**
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index 813c384b954..b33113b74be 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -27,11 +27,13 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.media.AudioAttributes;
import android.os.Bundle;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.text.TextUtils;
+import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
@@ -51,11 +53,14 @@ import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.util.DescriptionStyler;
+import java.util.List;
+
/**
* Activity which handles the actual enrolling for fingerprint.
*/
public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
+ private static final String TAG = "FingerprintEnrollEnrolling";
static final String TAG_SIDECAR = "sidecar";
private static final int PROGRESS_BAR_MAX = 10000;
@@ -86,6 +91,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
.build();
+ private boolean mCanAssumeUdfps;
private ProgressBar mProgressBar;
private ObjectAnimator mProgressAnim;
private TextView mStartMessage;
@@ -130,14 +136,35 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.fingerprint_enroll_enrolling);
+
+ final FingerprintManager fingerprintManager = getSystemService(FingerprintManager.class);
+ final List props =
+ fingerprintManager.getSensorPropertiesInternal();
+ mCanAssumeUdfps = props.size() == 1 && props.get(0).isAnyUdfpsType();
+
+ if (mCanAssumeUdfps) {
+ // Use a custom layout since animations, etc must be based off of the sensor's physical
+ // location.
+ setContentView(R.layout.udfps_enroll_enrolling);
+ final UdfpsEnrollLayout udfpsEnrollLayout = (UdfpsEnrollLayout) getLayoutInflater()
+ .inflate(R.layout.udfps_enroll_layout, null /* root */);
+ getLayout().addView(udfpsEnrollLayout);
+ } else {
+ setContentView(R.layout.fingerprint_enroll_enrolling);
+ }
+
setHeaderText(R.string.security_settings_fingerprint_enroll_repeat_title);
- mStartMessage = (TextView) findViewById(R.id.sud_layout_description);
- mRepeatMessage = (TextView) findViewById(R.id.repeat_message);
- mErrorText = (TextView) findViewById(R.id.error_text);
- mProgressBar = (ProgressBar) findViewById(R.id.fingerprint_progress_bar);
+
+ mStartMessage = findViewById(R.id.sud_layout_description);
+ mRepeatMessage = findViewById(R.id.repeat_message);
+ mErrorText = findViewById(R.id.error_text);
+ mProgressBar = findViewById(R.id.fingerprint_progress_bar);
mVibrator = getSystemService(Vibrator.class);
+ if (mCanAssumeUdfps) {
+ mProgressBar.setVisibility(View.INVISIBLE);
+ }
+
if (getLayout().shouldApplyPartnerHeavyThemeResource()) {
DescriptionStyler.applyPartnerCustomizationHeavyStyle(mRepeatMessage);
} else if (getLayout().shouldApplyPartnerResource()) {
@@ -193,7 +220,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
protected boolean shouldStartAutomatically() {
- return true;
+ return !mCanAssumeUdfps;
}
@Override
@@ -209,6 +236,12 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
@Override
public void onEnterAnimationComplete() {
super.onEnterAnimationComplete();
+
+ if (mCanAssumeUdfps) {
+ startEnrollment();
+ mProgressBar.setVisibility(View.VISIBLE);
+ }
+
mAnimationCancelled = false;
startIconAnimation();
}
@@ -252,7 +285,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
private void updateDescription() {
- if (mSidecar.getEnrollmentSteps() == -1) {
+ if (mSidecar == null || mSidecar.getEnrollmentSteps() == -1) {
mStartMessage.setVisibility(View.VISIBLE);
mRepeatMessage.setVisibility(View.INVISIBLE);
} else {
@@ -299,6 +332,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
}
private void updateProgress(boolean animate) {
+ if (mSidecar == null || !mSidecar.isEnrolling()) {
+ Log.d(TAG, "Enrollment not started yet");
+ return;
+ }
+
int progress = getProgress(
mSidecar.getEnrollmentSteps(), mSidecar.getEnrollmentRemaining());
if (animate) {
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollLayout.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollLayout.java
new file mode 100644
index 00000000000..ca27e840b8b
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollLayout.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.biometrics.fingerprint;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+import android.widget.LinearLayout;
+
+import com.android.settings.R;
+
+public class UdfpsEnrollLayout extends LinearLayout {
+
+ private static final String TAG = "UdfpsEnrollLayout";
+
+ private final FingerprintSensorPropertiesInternal mSensorProps;
+
+ public UdfpsEnrollLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mSensorProps = context.getSystemService(FingerprintManager.class)
+ .getSensorPropertiesInternal().get(0);
+ }
+
+ @Override
+ public void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ final View animation = findViewById(R.id.fingerprint_progress_bar);
+ final WindowManager wm = getContext().getSystemService(WindowManager.class);
+ final int statusbarHeight = Math.abs(wm.getCurrentWindowMetrics().getWindowInsets()
+ .getInsets(WindowInsets.Type.statusBars()).toRect().height());
+
+ // Calculate the amount of translation required. This is just re-arranged from
+ // animation.setY(mSensorProps.sensorLocationY-statusbarHeight-mSensorProps.sensorRadius)
+ // The translationY is the amount of extra height that should be added to the spacer
+ // above the animation
+ final int spaceHeight = mSensorProps.sensorLocationY - statusbarHeight
+ - mSensorProps.sensorRadius - animation.getTop();
+ animation.setTranslationY(spaceHeight);
+ }
+
+
+
+ @Override
+ public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ final View animation = findViewById(R.id.fingerprint_progress_bar);
+ final int sensorDiameter = mSensorProps.sensorRadius * 2;
+ // Multiply it slightly so that the progress bar is outside the UDFPS affordance, and that
+ // the animation is within the UDFPS affordance.
+ final int animationDiameter = (int) (sensorDiameter * 1);
+ animation.measure(MeasureSpec.makeMeasureSpec(animationDiameter, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(animationDiameter, MeasureSpec.EXACTLY));
+ }
+}