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

This CL calls methods in UdfpsEnrollUtils.java to announce a11y
message. Besides, scale factor calculation and UdfpsOverlayParams.java
are removed since they are added in settingslib/.

Test: manually tested on device:
      Turn on talkback and turn this flag on via adb command
      adb shell setprop
        sys.fflag.override.settings_show_udfps_enroll_in_settings true
Bug: 186873966, 260617060
Change-Id: I408ac6a36352aa4bfd4ac1374e3922163dbc2199
This commit is contained in:
Hao Dong
2023-01-17 10:39:46 +08:00
parent afb30cdd08
commit 24f8463af4
4 changed files with 51 additions and 146 deletions

View File

@@ -20,15 +20,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- The layout height/width are placeholders, which will be overwritten by
FingerprintSensorPropertiesInternal. -->
<View
android:id="@+id/udfps_enroll_accessibility_view"
android:layout_gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@string/accessibility_fingerprint_label"/>
<ImageView
android:id="@+id/udfps_enroll_animation_fp_progress_view"
android:layout_width="match_parent"

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,28 +195,15 @@ 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();
}
}
private void onFingerUp() {
if (mOverlayParams.isOptical()) {
mFingerprintDrawable.setShouldSkipDraw(false);
mFingerprintDrawable.invalidateSelf();
}
}
private int getPaddingX() {
return mProgressBarRadius;

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;
}
}