Merge "Add udfps/ and support a11y for the udfps enroll view."

This commit is contained in:
Hao Dong
2023-02-03 00:30:03 +00:00
committed by Android (Google) Code Review
4 changed files with 51 additions and 146 deletions

View File

@@ -32,6 +32,7 @@ import android.content.Intent;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
@@ -40,7 +41,6 @@ import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.Process;
@@ -48,10 +48,8 @@ import android.os.VibrationAttributes;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.text.TextUtils;
import android.util.DisplayUtils;
import android.util.FeatureFlagUtils;
import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.MotionEvent;
import android.view.OrientationEventListener;
@@ -77,6 +75,8 @@ import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.BiometricsEnrollEnrolling;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
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;
@@ -200,6 +200,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
private boolean mHaveShownSfpsLeftEdgeLottie;
private boolean mHaveShownSfpsRightEdgeLottie;
private boolean mShouldShowLottie;
private UdfpsUtils mUdfpsUtils;
private OrientationEventListener mOrientationEventListener;
private int mPreviousRotation = 0;
@@ -254,6 +255,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
mAccessibilityManager = getSystemService(AccessibilityManager.class);
mIsAccessibilityEnabled = mAccessibilityManager.isEnabled();
mUdfpsUtils = new UdfpsUtils();
final boolean isLayoutRtl = (TextUtils.getLayoutDirectionFromLocale(
Locale.getDefault()) == View.LAYOUT_DIRECTION_RTL);
@@ -280,7 +282,9 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
layoutContainer.setLayoutParams(lp);
if (FeatureFlagUtils.isEnabled(getApplicationContext(),
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
layout.addView(addUdfpsEnrollView(props.get(0)));
final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
layout.addView(udfpsEnrollView);
setOnHoverListener(true, layout, udfpsEnrollView);
}
setContentView(layout, lp);
break;
@@ -293,6 +297,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
R.layout.udfps_enroll_enrolling, null, false);
if (FeatureFlagUtils.isEnabled(getApplicationContext(),
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
final UdfpsEnrollView udfpsEnrollView = addUdfpsEnrollView(props.get(0));
if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
// In the portrait mode, set layout_container's height 0, so it's
// always shown at the bottom of the screen.
@@ -307,9 +312,11 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
final ViewGroup.LayoutParams containerLp =
portraitLayoutContainer.getLayoutParams();
containerLp.height = 0;
portraitLayoutContainer.addView(addUdfpsEnrollView(props.get(0)));
portraitLayoutContainer.addView(udfpsEnrollView);
setOnHoverListener(false, defaultLayout, udfpsEnrollView);
} else if (rotation == Surface.ROTATION_270) {
defaultLayout.addView(addUdfpsEnrollView(props.get(0)));
defaultLayout.addView(udfpsEnrollView);
setOnHoverListener(true, defaultLayout, udfpsEnrollView);
}
}
@@ -1197,17 +1204,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
DisplayInfo displayInfo = new DisplayInfo();
getDisplay().getDisplayInfo(displayInfo);
final Display.Mode maxDisplayMode =
DisplayUtils.getMaximumResolutionDisplayMode(displayInfo.supportedModes);
final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
maxDisplayMode.getPhysicalWidth(), maxDisplayMode.getPhysicalHeight(),
displayInfo.getNaturalWidth(), displayInfo.getNaturalHeight());
if (scaleFactor == Float.POSITIVE_INFINITY) {
mScaleFactor = 1f;
} else {
mScaleFactor = scaleFactor;
}
mScaleFactor = mUdfpsUtils.getScaleFactor(displayInfo);
Rect udfpsBounds = udfpsProps.getLocation().getRect();
udfpsBounds.scale(mScaleFactor);
@@ -1217,16 +1214,13 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
displayInfo.getNaturalWidth(), /* right */
displayInfo.getNaturalHeight() /* botom */);
// TODO(b/260617060): Extract this logic into a 3rd party library for both Settings and
// SysUI to depend on.
UdfpsOverlayParams params = new UdfpsOverlayParams(
udfpsBounds,
overlayBounds,
displayInfo.getNaturalWidth(),
displayInfo.getNaturalHeight(),
mScaleFactor,
displayInfo.rotation,
udfpsProps.sensorType == FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
displayInfo.rotation);
udfpsEnrollView.setOverlayParams(params);
@@ -1244,6 +1238,31 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
return udfpsEnrollView;
}
private void setOnHoverListener(boolean isLandscape, GlifLayout enrollLayout,
UdfpsEnrollView udfpsEnrollView) {
if (!mIsAccessibilityEnabled) return;
final Context context = getApplicationContext();
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(
mAccessibilityManager.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);
}
public static class IconTouchDialog extends InstrumentedDialogFragment {
@Override

View File

@@ -25,7 +25,6 @@ import android.util.AttributeSet;
import android.util.RotationUtils;
import android.view.Gravity;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -34,11 +33,13 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
import com.android.settingslib.udfps.UdfpsOverlayParams;
/**
* View corresponding with udfps_enroll_view.xml
*/
public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Listener {
private static final String TAG = "UdfpsEnrollView";
@NonNull
private final UdfpsEnrollDrawable mFingerprintDrawable;
@NonNull
@@ -98,12 +99,15 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
onFingerDown();
}
@Override
public void onPointerUp(int sensorId) {
onFingerUp();
}
public UdfpsOverlayParams getOverlayParams() {
return mOverlayParams;
}
void setOverlayParams(UdfpsOverlayParams params) {
mOverlayParams = params;
@@ -124,7 +128,6 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
private void onSensorRectUpdated() {
updateDimensions();
updateAccessibilityViewLocation();
// Updates sensor rect in relation to the overlay view
mSensorRect.set(getPaddingX(), getPaddingY(),
@@ -135,7 +138,7 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
private void updateDimensions() {
// Original sensorBounds assume portrait mode.
final Rect rotatedBounds = mOverlayParams.getSensorBounds();
final Rect rotatedBounds = new Rect(mOverlayParams.getSensorBounds());
int rotation = mOverlayParams.getRotation();
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
RotationUtils.rotateBounds(
@@ -192,27 +195,14 @@ public class UdfpsEnrollView extends FrameLayout implements UdfpsEnrollHelper.Li
setLayoutParams(params);
}
private void updateAccessibilityViewLocation() {
View fingerprintAccessibilityView = findViewById(R.id.udfps_enroll_accessibility_view);
ViewGroup.LayoutParams params = fingerprintAccessibilityView.getLayoutParams();
params.width = mOverlayParams.getSensorBounds().width();
params.height = mOverlayParams.getSensorBounds().height();
fingerprintAccessibilityView.setLayoutParams(params);
fingerprintAccessibilityView.requestLayout();
}
private void onFingerDown() {
if (mOverlayParams.isOptical()) {
mFingerprintDrawable.setShouldSkipDraw(true);
mFingerprintDrawable.invalidateSelf();
}
mFingerprintDrawable.setShouldSkipDraw(true);
mFingerprintDrawable.invalidateSelf();
}
private void onFingerUp() {
if (mOverlayParams.isOptical()) {
mFingerprintDrawable.setShouldSkipDraw(false);
mFingerprintDrawable.invalidateSelf();
}
mFingerprintDrawable.setShouldSkipDraw(false);
mFingerprintDrawable.invalidateSelf();
}
private int getPaddingX() {

View File

@@ -1,95 +0,0 @@
/*
* Copyright (C) 2022 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.graphics.Rect;
import androidx.annotation.NonNull;
/**
* Collection of parameters that define an under-display fingerprint sensor (UDFPS) overlay.
*
* [sensorBounds] coordinates of the bounding box around the sensor in natural orientation, in
* pixels, for the current resolution.
*
* [overlayBounds] coordinates of the UI overlay in natural orientation, in pixels, for the current
* resolution.
*
* [naturalDisplayWidth] width of the physical display in natural orientation, in pixels, for the
* current resolution.
*
* [naturalDisplayHeight] height of the physical display in natural orientation, in pixels, for the
* current resolution.
*
* [scaleFactor] ratio of a dimension in the current resolution to the corresponding dimension in
* the native resolution.
*
* [rotation] current rotation of the display.
*/
public final class UdfpsOverlayParams {
@NonNull
private final Rect mSensorBounds;
@NonNull
private final Rect mOverlayBounds;
private final int mNaturalDisplayWidth;
private final int mNaturalDisplayHeight;
private final float mScaleFactor;
private final int mRotation;
private final boolean mIsOptical;
public UdfpsOverlayParams(@NonNull Rect sensorBounds, @NonNull Rect overlayBounds,
int naturalDisplayWidth, int naturalDisplayHeight, float scaleFactor, int rotation,
boolean isOptical) {
mSensorBounds = sensorBounds;
mOverlayBounds = overlayBounds;
mNaturalDisplayWidth = naturalDisplayWidth;
mNaturalDisplayHeight = naturalDisplayHeight;
mScaleFactor = scaleFactor;
mRotation = rotation;
mIsOptical = isOptical;
}
@NonNull
public Rect getSensorBounds() {
return mSensorBounds;
}
@NonNull
public Rect getOverlayBounds() {
return mOverlayBounds;
}
public int getNaturalDisplayWidth() {
return mNaturalDisplayWidth;
}
public int getNaturalDisplayHeight() {
return mNaturalDisplayHeight;
}
public float getScaleFactor() {
return mScaleFactor;
}
public int getRotation() {
return mRotation;
}
public boolean isOptical() {
return mIsOptical;
}
}