Merge "Refactor FingerprintEnrollEnrolling to fragment" into udc-dev am: 98d2e83c3d
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Settings/+/21508164
Change-Id: I4f7b42e2cadbed273b94e91207d1dfa4f8b89464
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
index f7f138c..70fdbf0 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollHelper.java
@@ -142,7 +142,10 @@
setRetainInstance(true);
}
- void onEnrollmentProgress(int totalSteps, int remaining) {
+ /**
+ * Called when a enroll progress update
+ */
+ public void onEnrollmentProgress(int totalSteps, int remaining) {
if (mTotalSteps == -1) {
mTotalSteps = totalSteps;
}
@@ -161,25 +164,37 @@
}
}
- void onEnrollmentHelp() {
+ /**
+ * Called when a receive error has been encountered during enrollment.
+ */
+ public void onEnrollmentHelp() {
if (mListener != null) {
mListener.onEnrollmentHelp(mRemainingSteps, mTotalSteps);
}
}
- void onAcquired(boolean isAcquiredGood) {
+ /**
+ * Called when a fingerprint image has been acquired, but wasn't processed yet.
+ */
+ public void onAcquired(boolean isAcquiredGood) {
if (mListener != null && mTotalSteps != -1) {
mListener.onAcquired(isAcquiredGood && animateIfLastStep());
}
}
- void onPointerDown(int sensorId) {
+ /**
+ * Called when pointer down
+ */
+ public void onPointerDown(int sensorId) {
if (mListener != null) {
mListener.onPointerDown(sensorId);
}
}
- void onPointerUp(int sensorId) {
+ /**
+ * Called when pointer up
+ */
+ public void onPointerUp(int sensorId) {
if (mListener != null) {
mListener.onPointerUp(sensorId);
}
diff --git a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java
index 96b49aa..6e42059 100644
--- a/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java
+++ b/src/com/android/settings/biometrics/fingerprint/UdfpsEnrollView.java
@@ -108,7 +108,10 @@
return mOverlayParams;
}
- void setOverlayParams(UdfpsOverlayParams params) {
+ /**
+ * Set UdfpsOverlayParams
+ */
+ public void setOverlayParams(UdfpsOverlayParams params) {
mOverlayParams = params;
post(() -> {
@@ -121,7 +124,10 @@
});
}
- void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
+ /**
+ * Set UdfpsEnrollHelper
+ */
+ public void setEnrollHelper(UdfpsEnrollHelper enrollHelper) {
mFingerprintDrawable.setEnrollHelper(enrollHelper);
enrollHelper.setListener(this);
}
@@ -193,6 +199,8 @@
params.height = rotatedBounds.height() + 2 * getPaddingX();
params.width = rotatedBounds.width() + 2 * getPaddingY();
setLayoutParams(params);
+
+
}
private void onFingerDown() {
diff --git a/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java b/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java
index 8777b4f..20d7f1f 100644
--- a/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java
+++ b/src/com/android/settings/biometrics2/data/repository/AccessibilityRepository.java
@@ -65,4 +65,13 @@
public void sendAccessibilityEvent(@NonNull AccessibilityEvent event) {
mAccessibilityManager.sendAccessibilityEvent(event);
}
+
+ /**
+ * Returns if the touch exploration in the system is enabled.
+ *
+ * @return True if touch exploration is enabled, false otherwise.
+ */
+ public boolean isTouchExplorationEnabled() {
+ return mAccessibilityManager.isTouchExplorationEnabled();
+ }
}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
index a91e206..be18b9c 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
@@ -35,7 +35,6 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
-import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -329,12 +328,7 @@
}
private void announceEnrollmentProgress(CharSequence announcement) {
- AccessibilityEvent event = new AccessibilityEvent();
- event.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
- event.setClassName(getClass().getName());
- event.setPackageName(getClass().getPackageName());
- event.getText().add(announcement);
- mEnrollingViewModel.sendAccessibilityEvent(event);
+ mEnrollingViewModel.sendAccessibilityEvent(announcement);
}
private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java
index ad6abf1..4cf3573 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java
@@ -22,18 +22,23 @@
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
+import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.drawable.Animatable2;
-import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
+import android.view.DisplayInfo;
import android.view.LayoutInflater;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -47,15 +52,20 @@
import com.android.settings.R;
import com.android.settings.biometrics.BiometricUtils;
+import com.android.settings.biometrics.fingerprint.UdfpsEnrollHelper;
+import com.android.settings.biometrics.fingerprint.UdfpsEnrollView;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
import com.android.settingslib.display.DisplayDensityUtils;
+import com.android.settingslib.udfps.UdfpsOverlayParams;
+import com.android.settingslib.udfps.UdfpsUtils;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieCompositionFactory;
+import com.google.android.setupcompat.template.FooterActionButton;
import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifLayout;
@@ -70,9 +80,6 @@
private static final String TAG = FingerprintEnrollEnrollingUdfpsFragment.class.getSimpleName();
private static final int PROGRESS_BAR_MAX = 10000;
- private static final long ICON_TOUCH_DURATION_UNTIL_DIALOG_SHOWN = 500;
- private static final int ICON_TOUCH_COUNT_SHOW_UNTIL_DIALOG_SHOWN = 3;
- private static final int HINT_TIMEOUT_DURATION = 2500;
private static final int STAGE_UNKNOWN = -1;
private static final int STAGE_CENTER = 0;
@@ -100,35 +107,52 @@
private GlifLayout mView;
private TextView mErrorText;
private FooterBarMixin mFooterBarMixin;
- private AnimatedVectorDrawable mIconAnimationDrawable;
- private AnimatedVectorDrawable mIconBackgroundBlinksDrawable;
private boolean mShouldShowLottie;
private boolean mIsAccessibilityEnabled;
private final View.OnClickListener mOnSkipClickListener =
(v) -> mEnrollingViewModel.onCancelledDueToOnSkipPressed();
- private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
+
+ private Observer<EnrollmentProgress> mProgressObserver = progress -> {
+ if (progress != null) {
+ onEnrollmentProgressChange(progress);
+ }
+ };
+ private Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
+ if (helpMessage != null) {
+ onEnrollmentHelp(helpMessage.getMsgId(), helpMessage.getStr());
+ }
+ };
+ private Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
// TODO
};
- private final Observer<EnrollmentStatusMessage> mHelpMessageObserver = helpMessage -> {
- // TODO
- };
- private final Observer<EnrollmentStatusMessage> mErrorMessageObserver = errorMessage -> {
- // TODO
- };
- private final Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
- // TODO
+ private Observer<Boolean> mAcquireObserver = isAcquiredGood -> {
+ if (isAcquiredGood != null) {
+ onAcquired(isAcquiredGood);
+ }
};
private final Observer<Integer> mPointerDownObserver = sensorId -> {
- // TODO
+ if (sensorId != null) {
+ onPointerDown(sensorId);
+ }
};
private final Observer<Integer> mPointerUpObserver = sensorId -> {
- // TODO
+ if (sensorId != null) {
+ onPointerUp(sensorId);
+ }
};
private int mIconTouchCount;
+ private UdfpsUtils mUdfpsUtils;
+ private float mScaleFactor = 1.0f;
+ //TODO UdfpsEnrollHelper should not be a Fragment, we should tell enrollview & progress
+ // drawable enough information EnrollView & ProgressDrawable should draw themselves without
+ // UdfpsEnrollHelper
+ private UdfpsEnrollHelper mUdfpsEnrollHelper;
+
+
@Override
public void onAttach(@NonNull Context context) {
final FragmentActivity activity = getActivity();
@@ -176,6 +200,10 @@
super.onCreate(savedInstanceState);
mEnrollingViewModel.restoreSavedState(savedInstanceState);
mIsAccessibilityEnabled = mEnrollingViewModel.isAccessibilityEnabled();
+ mUdfpsUtils = new UdfpsUtils();
+ mUdfpsEnrollHelper = new UdfpsEnrollHelper(getActivity(), getActivity().getSystemService(
+ FingerprintManager.class
+ ));
}
@Override
@@ -188,13 +216,15 @@
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mView = initUdfpsLayout(inflater, container);
+
return mView;
}
private GlifLayout initUdfpsLayout(LayoutInflater inflater, ViewGroup container) {
final GlifLayout containView = (GlifLayout) inflater.inflate(
R.layout.udfps_enroll_enrolling, container, false);
-
+ final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(inflater,
+ mEnrollingViewModel.getFirstFingerprintSensorPropertiesInternal());
final int rotation = mRotationViewModel.getLiveData().getValue();
if (rotation == Surface.ROTATION_90) {
final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale(
@@ -207,19 +237,36 @@
isLayoutRtl ? 0 : (int) getResources().getDimension(
R.dimen.rotation_90_enroll_padding_end),
0);
+
final LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
lp.setMarginEnd((int) getResources().getDimension(
R.dimen.rotation_90_enroll_margin_end));
layoutContainer.setLayoutParams(lp);
+ containView.addView(udfpsEnrollView);
+ containView.setClipChildren(false);
+ containView.setClipToPadding(false);
containView.setLayoutParams(lp);
+ setOnHoverListener(true, containView, udfpsEnrollView);
+ } else if (rotation == Surface.ROTATION_270) {
+ containView.addView(udfpsEnrollView);
+ containView.setClipChildren(false);
+ containView.setClipToPadding(false);
+ setOnHoverListener(true, containView, udfpsEnrollView);
+ } else {
+ final FrameLayout portraitLayoutContainer = containView.findViewById(
+ R.id.layout_container);
+ portraitLayoutContainer.addView(udfpsEnrollView);
+ ViewGroup parent = ((ViewGroup) portraitLayoutContainer.getParent());
+ parent.setClipChildren(false);
+ parent.setClipToPadding(false);
+ setOnHoverListener(false, containView, udfpsEnrollView);
}
final Activity activity = getActivity();
new GlifLayoutHelper(activity, containView).setDescriptionText(
getString(R.string.security_settings_udfps_enroll_start_message));
- updateTitleAndDescription();
mShouldShowLottie = shouldShowLottie();
boolean isLandscape = BiometricUtils.isReverseLandscape(activity)
@@ -245,6 +292,19 @@
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(
activity, android.R.interpolator.fast_out_linear_in);
+ final LinearLayout buttonContainer = mFooterBarMixin.getButtonContainer();
+ View spaceView = null;
+ for (int i = 0; i < buttonContainer.getChildCount(); i++) {
+ if (!(buttonContainer.getChildAt(i) instanceof FooterActionButton)) {
+ spaceView = buttonContainer.getChildAt(i);
+ break;
+ }
+ }
+ if (spaceView != null) {
+ spaceView.setVisibility(View.GONE);
+ buttonContainer.getLayoutParams().width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ }
+
return containView;
}
@@ -298,6 +358,9 @@
final int progress = getProgress(enrollmentProgress);
+ mUdfpsEnrollHelper.onEnrollmentProgress(enrollmentProgress.getSteps(),
+ enrollmentProgress.getRemaining());
+
if (animate) {
animateProgress(progress);
} else if (progress >= PROGRESS_BAR_MAX) {
@@ -319,6 +382,38 @@
super.onDestroy();
}
+ private UdfpsEnrollView addUdfpsEnrollView(LayoutInflater inflater,
+ FingerprintSensorPropertiesInternal udfpsProps) {
+
+ UdfpsEnrollView enrollView = (UdfpsEnrollView) inflater.inflate(R.layout.udfps_enroll_view,
+ null, false);
+ DisplayInfo displayInfo = new DisplayInfo();
+ getActivity().getDisplay().getDisplayInfo(displayInfo);
+ mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
+ Rect udfpsBounds = udfpsProps.getLocation().getRect();
+ udfpsBounds.scale(mScaleFactor);
+
+ final Rect overlayBounds = new Rect(
+ 0, /* left */
+ displayInfo.getNaturalHeight() / 2, /* top */
+ displayInfo.getNaturalWidth(), /* right */
+ displayInfo.getNaturalHeight() /* botom */);
+
+ UdfpsOverlayParams params = new UdfpsOverlayParams(
+ udfpsBounds,
+ overlayBounds,
+ displayInfo.getNaturalWidth(),
+ displayInfo.getNaturalHeight(),
+ mScaleFactor,
+ displayInfo.rotation);
+
+ enrollView.setOverlayParams(params);
+
+ enrollView.setEnrollHelper(mUdfpsEnrollHelper);
+
+ return enrollView;
+ }
+
private void animateProgress(int progress) {
// UDFPS animations are owned by SystemUI
if (progress >= PROGRESS_BAR_MAX) {
@@ -462,16 +557,10 @@
}
private void startIconAnimation() {
- if (mIconAnimationDrawable != null) {
- mIconAnimationDrawable.start();
- }
}
private void stopIconAnimation() {
mAnimationCancelled = true;
- if (mIconAnimationDrawable != null) {
- mIconAnimationDrawable.stop();
- }
}
private int getCurrentStage() {
@@ -545,6 +634,79 @@
});
}
+ private void setOnHoverListener(boolean isLandscape, GlifLayout enrollLayout,
+ UdfpsEnrollView udfpsEnrollView) {
+ if (!mIsAccessibilityEnabled) return;
+
+ final Context context = getActivity();
+ final View.OnHoverListener onHoverListener = (v, event) -> {
+ // Map the touch to portrait mode if the device is in
+ // landscape mode.
+ final Point scaledTouch =
+ mUdfpsUtils.getTouchInNativeCoordinates(event.getPointerId(0),
+ event, udfpsEnrollView.getOverlayParams());
+
+ final String theStr = mUdfpsUtils.onTouchOutsideOfSensorArea(
+ mEnrollingViewModel.isTouchExplorationEnabled(), context,
+ scaledTouch.x, scaledTouch.y, udfpsEnrollView.getOverlayParams());
+ if (theStr != null) {
+ v.announceForAccessibility(theStr);
+ }
+ return false;
+ };
+
+ enrollLayout.findManagedViewById(isLandscape ? R.id.sud_landscape_content_area
+ : R.id.sud_layout_content).setOnHoverListener(onHoverListener);
+ }
+
+ private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
+ updateProgress(true /* animate */, progress);
+
+ updateTitleAndDescription();
+
+ if (mIsAccessibilityEnabled) {
+ final int steps = progress.getSteps();
+ final int remaining = progress.getRemaining();
+ final int percent = (int) (((float) (steps - remaining) / (float) steps) * 100);
+ CharSequence announcement = getActivity().getString(
+ R.string.security_settings_udfps_enroll_progress_a11y_message, percent);
+ mEnrollingViewModel.sendAccessibilityEvent(announcement);
+ }
+
+ }
+
+ private void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
+ if (!TextUtils.isEmpty(helpString)) {
+ showError(helpString);
+ mUdfpsEnrollHelper.onEnrollmentHelp();
+ }
+ }
+
+ private void onAcquired(boolean isAcquiredGood) {
+ if (mUdfpsEnrollHelper != null) {
+ mUdfpsEnrollHelper.onAcquired(isAcquiredGood);
+ }
+ }
+
+ private void onPointerDown(int sensorId) {
+ if (mUdfpsEnrollHelper != null) {
+ mUdfpsEnrollHelper.onPointerDown(sensorId);
+ }
+ }
+
+ private void onPointerUp(int sensorId) {
+ if (mUdfpsEnrollHelper != null) {
+ mUdfpsEnrollHelper.onPointerUp(sensorId);
+ }
+ }
+
+ private void showError(CharSequence error) {
+ mView.setHeaderText(error);
+ mView.getHeaderTextView().setContentDescription(error);
+ new GlifLayoutHelper(getActivity(), mView).setDescriptionText("");
+ }
+
+
private final Runnable mShowDialogRunnable = new Runnable() {
@Override
public void run() {
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
index 6a9adb7..6fde44c 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
@@ -23,7 +23,6 @@
import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.util.Log;
-import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -282,19 +281,23 @@
/**
* Sends an {@link AccessibilityEvent}.
- *
- * @param event The event to send.
- *
- * @throws IllegalStateException if accessibility is not enabled.
- *
- * <strong>Note:</strong> The preferred mechanism for sending custom accessibility
- * events is through calling
- * {@link android.view.ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
- * instead of this method to allow predecessors to augment/filter events sent by
- * their descendants.
*/
- public void sendAccessibilityEvent(@NonNull AccessibilityEvent event) {
- mAccessibilityRepository.sendAccessibilityEvent(event);
+ public void sendAccessibilityEvent(CharSequence announcement) {
+ AccessibilityEvent e = AccessibilityEvent.obtain();
+ e.setEventType(AccessibilityEvent.TYPE_ANNOUNCEMENT);
+ e.setClassName(getClass().getName());
+ e.setPackageName(getApplication().getPackageName());
+ e.getText().add(announcement);
+ mAccessibilityRepository.sendAccessibilityEvent(e);
+ }
+
+ /**
+ * Returns if the touch exploration in the system is enabled.
+ *
+ * @return True if touch exploration is enabled, false otherwise.
+ */
+ public boolean isTouchExplorationEnabled() {
+ return mAccessibilityRepository.isTouchExplorationEnabled();
}
/**