Add udfps/ and support a11y for the udfps enroll view.
This CL:
1. Adds udfps/ in settingslib/ for sharing methods.
2. Moves scale factor and UdfpsOverlayParams.java to settingslib/.
3. Adds an accessibility view for fingerprint sensor annoucement.
Test: atest UdfpsControllerOverlayTest
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: I083ccfccb435ad5baf29afd377098dd127a63f80
This commit is contained in:
@@ -1626,4 +1626,12 @@
|
||||
<string name="back_navigation_animation_summary">Enable system animations for predictive back.</string>
|
||||
<!-- Developer setting: enable animations when a back gesture is executed, full explanation[CHAR LIMIT=NONE] -->
|
||||
<string name="back_navigation_animation_dialog">This setting enables system animations for predictive gesture animation. It requires setting per-app "enableOnBackInvokedCallback" to true in the manifest file.</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] Messages shown when users press outside of udfps region during -->
|
||||
<string-array name="udfps_accessibility_touch_hints">
|
||||
<item>Move left</item>
|
||||
<item>Move down</item>
|
||||
<item>Move right</item>
|
||||
<item>Move up</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.android.systemui.biometrics
|
||||
package com.android.settingslib.udfps
|
||||
|
||||
import android.graphics.Rect
|
||||
import android.view.Surface
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.settingslib.udfps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.util.DisplayUtils;
|
||||
import android.util.Log;
|
||||
import android.util.RotationUtils;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
/** Utility class for working with udfps. */
|
||||
public class UdfpsUtils {
|
||||
private static final String TAG = "UdfpsUtils";
|
||||
|
||||
/**
|
||||
* Gets the scale factor representing the user's current resolution / the stable (default)
|
||||
* resolution.
|
||||
*
|
||||
* @param displayInfo The display information.
|
||||
*/
|
||||
public float getScaleFactor(DisplayInfo displayInfo) {
|
||||
Display.Mode maxDisplayMode =
|
||||
DisplayUtils.getMaximumResolutionDisplayMode(displayInfo.supportedModes);
|
||||
float scaleFactor =
|
||||
DisplayUtils.getPhysicalPixelDisplaySizeRatio(
|
||||
maxDisplayMode.getPhysicalWidth(),
|
||||
maxDisplayMode.getPhysicalHeight(),
|
||||
displayInfo.getNaturalWidth(),
|
||||
displayInfo.getNaturalHeight()
|
||||
);
|
||||
return (scaleFactor == Float.POSITIVE_INFINITY) ? 1f : scaleFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the touch in native coordinates. Map the touch to portrait mode if the device is in
|
||||
* landscape mode.
|
||||
*
|
||||
* @param idx The pointer identifier.
|
||||
* @param event The MotionEvent object containing full information about the event.
|
||||
* @param udfpsOverlayParams The [UdfpsOverlayParams] used.
|
||||
* @return The mapped touch event.
|
||||
*/
|
||||
public Point getTouchInNativeCoordinates(int idx, MotionEvent event,
|
||||
UdfpsOverlayParams udfpsOverlayParams) {
|
||||
Point portraitTouch = new Point((int) event.getRawX(idx), (int) event.getRawY(idx));
|
||||
int rot = udfpsOverlayParams.getRotation();
|
||||
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
|
||||
RotationUtils.rotatePoint(
|
||||
portraitTouch,
|
||||
RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
|
||||
udfpsOverlayParams.getLogicalDisplayWidth(),
|
||||
udfpsOverlayParams.getLogicalDisplayHeight()
|
||||
);
|
||||
}
|
||||
|
||||
// Scale the coordinates to native resolution.
|
||||
float scale = udfpsOverlayParams.getScaleFactor();
|
||||
portraitTouch.x = (int) (portraitTouch.x / scale);
|
||||
portraitTouch.y = (int) (portraitTouch.y / scale);
|
||||
return portraitTouch;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function computes the angle of touch relative to the sensor and maps the angle to a list
|
||||
* of help messages which are announced if accessibility is enabled.
|
||||
*
|
||||
* @return Whether the announcing string is null
|
||||
*/
|
||||
public String onTouchOutsideOfSensorArea(boolean touchExplorationEnabled,
|
||||
Context context, int touchX, int touchY, UdfpsOverlayParams udfpsOverlayParams) {
|
||||
if (!touchExplorationEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String[] touchHints = context.getResources().getStringArray(
|
||||
R.array.udfps_accessibility_touch_hints);
|
||||
if (touchHints.length != 4) {
|
||||
Log.e(TAG, "expected exactly 4 touch hints, got " + touchHints.length + "?");
|
||||
return null;
|
||||
}
|
||||
|
||||
// Scale the coordinates to native resolution.
|
||||
float scale = udfpsOverlayParams.getScaleFactor();
|
||||
float scaledSensorX = udfpsOverlayParams.getSensorBounds().centerX() / scale;
|
||||
float scaledSensorY = udfpsOverlayParams.getSensorBounds().centerY() / scale;
|
||||
String theStr =
|
||||
onTouchOutsideOfSensorAreaImpl(
|
||||
touchHints,
|
||||
touchX,
|
||||
touchY,
|
||||
scaledSensorX,
|
||||
scaledSensorY,
|
||||
udfpsOverlayParams.getRotation()
|
||||
);
|
||||
Log.v(TAG, "Announcing touch outside : $theStr");
|
||||
return theStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function computes the angle of touch relative to the sensor and maps the angle to a list
|
||||
* of help messages which are announced if accessibility is enabled.
|
||||
*
|
||||
* There are 4 quadrants of the circle (90 degree arcs)
|
||||
*
|
||||
* [315, 360] && [0, 45) -> touchHints[0] = "Move Fingerprint to the left" [45, 135) ->
|
||||
* touchHints[1] = "Move Fingerprint down" And so on.
|
||||
*/
|
||||
private String onTouchOutsideOfSensorAreaImpl(String[] touchHints, float touchX,
|
||||
float touchY, float sensorX, float sensorY, int rotation) {
|
||||
float xRelativeToSensor = touchX - sensorX;
|
||||
// Touch coordinates are with respect to the upper left corner, so reverse
|
||||
// this calculation
|
||||
float yRelativeToSensor = sensorY - touchY;
|
||||
var angleInRad = Math.atan2(yRelativeToSensor, xRelativeToSensor);
|
||||
// If the radians are negative, that means we are counting clockwise.
|
||||
// So we need to add 360 degrees
|
||||
if (angleInRad < 0.0) {
|
||||
angleInRad += 2.0 * Math.PI;
|
||||
}
|
||||
// rad to deg conversion
|
||||
double degrees = Math.toDegrees(angleInRad);
|
||||
double degreesPerBucket = 360.0 / touchHints.length;
|
||||
double halfBucketDegrees = degreesPerBucket / 2.0;
|
||||
// The mapping should be as follows
|
||||
// [315, 360] && [0, 45] -> 0
|
||||
// [45, 135] -> 1
|
||||
int index = (int) ((degrees + halfBucketDegrees) % 360 / degreesPerBucket);
|
||||
index %= touchHints.length;
|
||||
|
||||
// A rotation of 90 degrees corresponds to increasing the index by 1.
|
||||
if (rotation == Surface.ROTATION_90) {
|
||||
index = (index + 1) % touchHints.length;
|
||||
}
|
||||
if (rotation == Surface.ROTATION_270) {
|
||||
index = (index + 3) % touchHints.length;
|
||||
}
|
||||
return touchHints[index];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.settingslib.udfps;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.view.Surface;
|
||||
|
||||
import com.android.settingslib.R;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
import org.robolectric.RobolectricTestRunner;
|
||||
import org.robolectric.RuntimeEnvironment;
|
||||
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
public class UdfpsUtilsTest {
|
||||
@Rule
|
||||
public final MockitoRule rule = MockitoJUnit.rule();
|
||||
|
||||
private Context mContext;
|
||||
private String[] mTouchHints;
|
||||
private UdfpsUtils mUdfpsUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
mTouchHints = mContext.getResources().getStringArray(
|
||||
R.array.udfps_accessibility_touch_hints);
|
||||
mUdfpsUtils = new UdfpsUtils();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTouchOutsideAreaNoRotation() {
|
||||
int rotation = Surface.ROTATION_0;
|
||||
// touch at 0 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, 0/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[0]);
|
||||
// touch at 90 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, -1/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[1]);
|
||||
// touch at 180 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
-1 /* touchX */, 0/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[2]);
|
||||
// touch at 270 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, 1/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[3]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTouchOutsideAreaNoRotation90Degrees() {
|
||||
int rotation = Surface.ROTATION_90;
|
||||
// touch at 0 degrees -> 90 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, 0 /* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[1]);
|
||||
// touch at 90 degrees -> 180 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, -1 /* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[2]);
|
||||
// touch at 180 degrees -> 270 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
-1 /* touchX */, 0 /* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[3]);
|
||||
// touch at 270 degrees -> 0 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, 1/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[0]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTouchOutsideAreaNoRotation270Degrees() {
|
||||
int rotation = Surface.ROTATION_270;
|
||||
// touch at 0 degrees -> 270 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, 0/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[3]);
|
||||
// touch at 90 degrees -> 0 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, -1/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[0]);
|
||||
// touch at 180 degrees -> 90 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
-1 /* touchX */, 0/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[1]);
|
||||
// touch at 270 degrees -> 180 degrees
|
||||
assertThat(
|
||||
mUdfpsUtils.onTouchOutsideOfSensorArea(true, mContext,
|
||||
0 /* touchX */, 1/* touchY */,
|
||||
new UdfpsOverlayParams(new Rect(), new Rect(), 0, 0, 1f, rotation)
|
||||
)
|
||||
).isEqualTo(mTouchHints[2]);
|
||||
}
|
||||
}
|
||||
@@ -19,4 +19,12 @@
|
||||
android:id="@+id/udfps_animation_view"
|
||||
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"/>
|
||||
</com.android.systemui.biometrics.UdfpsFpmEmptyView>
|
||||
|
||||
@@ -908,14 +908,6 @@
|
||||
<!-- Message shown when non-bypass face authentication succeeds. [CHAR LIMIT=60] -->
|
||||
<string name="keyguard_face_successful_unlock_alt1">Face recognized</string>
|
||||
|
||||
<!-- Messages shown when users press outside of udfps region during -->
|
||||
<string-array name="udfps_accessibility_touch_hints">
|
||||
<item>Move left</item>
|
||||
<item>Move down</item>
|
||||
<item>Move right</item>
|
||||
<item>Move up</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Message shown when face authentication fails and the pin pad is visible. [CHAR LIMIT=60] -->
|
||||
<string name="keyguard_retry">Swipe up to try again</string>
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserManager;
|
||||
import android.util.DisplayUtils;
|
||||
import android.util.Log;
|
||||
import android.util.RotationUtils;
|
||||
import android.util.SparseBooleanArray;
|
||||
@@ -69,6 +68,8 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.os.SomeArgs;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams;
|
||||
import com.android.settingslib.udfps.UdfpsUtils;
|
||||
import com.android.systemui.CoreStartable;
|
||||
import com.android.systemui.biometrics.domain.interactor.BiometricPromptCredentialInteractor;
|
||||
import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
|
||||
@@ -169,6 +170,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
@NonNull private final UserManager mUserManager;
|
||||
@NonNull private final LockPatternUtils mLockPatternUtils;
|
||||
@NonNull private final InteractionJankMonitor mInteractionJankMonitor;
|
||||
@NonNull private final UdfpsUtils mUdfpsUtils;
|
||||
private final @Background DelayableExecutor mBackgroundExecutor;
|
||||
private final DisplayInfo mCachedDisplayInfo = new DisplayInfo();
|
||||
|
||||
@@ -578,17 +580,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
*/
|
||||
private void updateSensorLocations() {
|
||||
mDisplay.getDisplayInfo(mCachedDisplayInfo);
|
||||
final Display.Mode maxDisplayMode =
|
||||
DisplayUtils.getMaximumResolutionDisplayMode(mCachedDisplayInfo.supportedModes);
|
||||
final float scaleFactor = android.util.DisplayUtils.getPhysicalPixelDisplaySizeRatio(
|
||||
maxDisplayMode.getPhysicalWidth(), maxDisplayMode.getPhysicalHeight(),
|
||||
mCachedDisplayInfo.getNaturalWidth(), mCachedDisplayInfo.getNaturalHeight());
|
||||
if (scaleFactor == Float.POSITIVE_INFINITY) {
|
||||
mScaleFactor = 1f;
|
||||
} else {
|
||||
mScaleFactor = scaleFactor;
|
||||
}
|
||||
|
||||
mScaleFactor = mUdfpsUtils.getScaleFactor(mCachedDisplayInfo);
|
||||
updateUdfpsLocation();
|
||||
updateFingerprintLocation();
|
||||
updateFaceLocation();
|
||||
@@ -732,7 +724,8 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
@NonNull InteractionJankMonitor jankMonitor,
|
||||
@Main Handler handler,
|
||||
@Background DelayableExecutor bgExecutor,
|
||||
@NonNull VibratorHelper vibrator) {
|
||||
@NonNull VibratorHelper vibrator,
|
||||
@NonNull UdfpsUtils udfpsUtils) {
|
||||
mContext = context;
|
||||
mExecution = execution;
|
||||
mUserManager = userManager;
|
||||
@@ -753,6 +746,7 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks,
|
||||
mSfpsEnrolledForUser = new SparseBooleanArray();
|
||||
mFaceEnrolledForUser = new SparseBooleanArray();
|
||||
mVibratorHelper = vibrator;
|
||||
mUdfpsUtils = udfpsUtils;
|
||||
|
||||
mLogContextInteractor = logContextInteractor;
|
||||
mBiometricPromptInteractor = biometricPromptInteractor;
|
||||
|
||||
@@ -50,10 +50,8 @@ import android.os.Trace;
|
||||
import android.os.VibrationAttributes;
|
||||
import android.os.VibrationEffect;
|
||||
import android.util.Log;
|
||||
import android.util.RotationUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityManager;
|
||||
@@ -66,6 +64,8 @@ import com.android.internal.logging.InstanceId;
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.keyguard.FaceAuthApiRequestReason;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams;
|
||||
import com.android.settingslib.udfps.UdfpsUtils;
|
||||
import com.android.systemui.Dumpable;
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||
import com.android.systemui.biometrics.dagger.BiometricsBackground;
|
||||
@@ -168,6 +168,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
@NonNull private final SessionTracker mSessionTracker;
|
||||
@NonNull private final AlternateBouncerInteractor mAlternateBouncerInteractor;
|
||||
@NonNull private final SecureSettings mSecureSettings;
|
||||
@NonNull private final UdfpsUtils mUdfpsUtils;
|
||||
|
||||
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
|
||||
// sensors, this, in addition to a lot of the code here, will be updated.
|
||||
@@ -266,7 +267,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
mUdfpsDisplayMode, mSecureSettings, requestId, reason, callback,
|
||||
(view, event, fromUdfpsView) -> onTouch(requestId, event,
|
||||
fromUdfpsView), mActivityLaunchAnimator, mFeatureFlags,
|
||||
mPrimaryBouncerInteractor, mAlternateBouncerInteractor)));
|
||||
mPrimaryBouncerInteractor, mAlternateBouncerInteractor, mUdfpsUtils)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -475,27 +476,6 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
&& mOverlayParams.getSensorBounds().contains((int) x, (int) y);
|
||||
}
|
||||
|
||||
private Point getTouchInNativeCoordinates(@NonNull MotionEvent event, int idx) {
|
||||
Point portraitTouch = new Point(
|
||||
(int) event.getRawX(idx),
|
||||
(int) event.getRawY(idx)
|
||||
);
|
||||
final int rot = mOverlayParams.getRotation();
|
||||
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
|
||||
RotationUtils.rotatePoint(portraitTouch,
|
||||
RotationUtils.deltaRotation(rot, Surface.ROTATION_0),
|
||||
mOverlayParams.getLogicalDisplayWidth(),
|
||||
mOverlayParams.getLogicalDisplayHeight()
|
||||
);
|
||||
}
|
||||
|
||||
// Scale the coordinates to native resolution.
|
||||
final float scale = mOverlayParams.getScaleFactor();
|
||||
portraitTouch.x = (int) (portraitTouch.x / scale);
|
||||
portraitTouch.y = (int) (portraitTouch.y / scale);
|
||||
return portraitTouch;
|
||||
}
|
||||
|
||||
private void tryDismissingKeyguard() {
|
||||
if (!mOnFingerDown) {
|
||||
playStartHaptic();
|
||||
@@ -713,7 +693,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
break;
|
||||
}
|
||||
// Map the touch to portrait mode if the device is in landscape mode.
|
||||
final Point scaledTouch = getTouchInNativeCoordinates(event, idx);
|
||||
final Point scaledTouch = mUdfpsUtils.getTouchInNativeCoordinates(
|
||||
idx, event, mOverlayParams);
|
||||
if (actionMoveWithinSensorArea) {
|
||||
if (mVelocityTracker == null) {
|
||||
// touches could be injected, so the velocity tracker may not have
|
||||
@@ -757,16 +738,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
+ "but serverRequest is null");
|
||||
return;
|
||||
}
|
||||
// Scale the coordinates to native resolution.
|
||||
final float scale = mOverlayParams.getScaleFactor();
|
||||
final float scaledSensorX =
|
||||
mOverlayParams.getSensorBounds().centerX() / scale;
|
||||
final float scaledSensorY =
|
||||
mOverlayParams.getSensorBounds().centerY() / scale;
|
||||
|
||||
mOverlay.onTouchOutsideOfSensorArea(
|
||||
scaledTouch.x, scaledTouch.y, scaledSensorX, scaledSensorY,
|
||||
mOverlayParams.getRotation());
|
||||
mOverlay.onTouchOutsideOfSensorArea(scaledTouch);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -838,7 +810,8 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
@NonNull SinglePointerTouchProcessor singlePointerTouchProcessor,
|
||||
@NonNull SessionTracker sessionTracker,
|
||||
@NonNull AlternateBouncerInteractor alternateBouncerInteractor,
|
||||
@NonNull SecureSettings secureSettings) {
|
||||
@NonNull SecureSettings secureSettings,
|
||||
@NonNull UdfpsUtils udfpsUtils) {
|
||||
mContext = context;
|
||||
mExecution = execution;
|
||||
mVibrator = vibrator;
|
||||
@@ -880,6 +853,7 @@ public class UdfpsController implements DozeReceiver, Dumpable {
|
||||
mPrimaryBouncerInteractor = primaryBouncerInteractor;
|
||||
mAlternateBouncerInteractor = alternateBouncerInteractor;
|
||||
mSecureSettings = secureSettings;
|
||||
mUdfpsUtils = udfpsUtils;
|
||||
|
||||
mTouchProcessor = mFeatureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)
|
||||
? singlePointerTouchProcessor : null;
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.SuppressLint
|
||||
import android.annotation.UiThread
|
||||
import android.content.Context
|
||||
import android.graphics.PixelFormat
|
||||
import android.graphics.Point
|
||||
import android.graphics.Rect
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_BP
|
||||
import android.hardware.biometrics.BiometricOverlayConstants.REASON_AUTH_KEYGUARD
|
||||
@@ -46,6 +47,8 @@ import android.view.accessibility.AccessibilityManager.TouchExplorationStateChan
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.settingslib.udfps.UdfpsUtils
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator
|
||||
import com.android.systemui.dump.DumpManager
|
||||
@@ -101,6 +104,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
private val primaryBouncerInteractor: PrimaryBouncerInteractor,
|
||||
private val alternateBouncerInteractor: AlternateBouncerInteractor,
|
||||
private val isDebuggable: Boolean = Build.IS_DEBUGGABLE,
|
||||
private val udfpsUtils: UdfpsUtils
|
||||
) {
|
||||
/** The view, when [isShowing], or null. */
|
||||
var overlayView: UdfpsView? = null
|
||||
@@ -239,7 +243,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
FeatureFlagUtils.SETTINGS_SHOW_UDFPS_ENROLL_IN_SETTINGS)) {
|
||||
// Enroll udfps UI is handled by settings, so use empty view here
|
||||
UdfpsFpmEmptyViewController(
|
||||
view.addUdfpsView(R.layout.udfps_fpm_empty_view),
|
||||
view.addUdfpsView(R.layout.udfps_fpm_empty_view){
|
||||
updateAccessibilityViewLocation(sensorBounds)
|
||||
},
|
||||
statusBarStateController,
|
||||
shadeExpansionStateManager,
|
||||
dialogManager,
|
||||
@@ -348,81 +354,18 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
|
||||
* the angle to a list of help messages which are announced if accessibility is enabled.
|
||||
*
|
||||
*/
|
||||
fun onTouchOutsideOfSensorArea(
|
||||
touchX: Float,
|
||||
touchY: Float,
|
||||
sensorX: Float,
|
||||
sensorY: Float,
|
||||
rotation: Int
|
||||
) {
|
||||
|
||||
if (!touchExplorationEnabled) {
|
||||
return
|
||||
fun onTouchOutsideOfSensorArea(scaledTouch: Point) {
|
||||
val theStr =
|
||||
udfpsUtils.onTouchOutsideOfSensorArea(
|
||||
touchExplorationEnabled,
|
||||
context,
|
||||
scaledTouch.x,
|
||||
scaledTouch.y,
|
||||
overlayParams
|
||||
)
|
||||
if (theStr != null) {
|
||||
animationViewController?.doAnnounceForAccessibility(theStr)
|
||||
}
|
||||
val touchHints =
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
if (touchHints.size != 4) {
|
||||
Log.e(TAG, "expected exactly 4 touch hints, got $touchHints.size?")
|
||||
return
|
||||
}
|
||||
val theStr = onTouchOutsideOfSensorAreaImpl(touchX, touchY, sensorX, sensorY, rotation)
|
||||
Log.v(TAG, "Announcing touch outside : " + theStr)
|
||||
animationViewController?.doAnnounceForAccessibility(theStr)
|
||||
}
|
||||
|
||||
/**
|
||||
* This function computes the angle of touch relative to the sensor and maps
|
||||
* the angle to a list of help messages which are announced if accessibility is enabled.
|
||||
*
|
||||
* There are 4 quadrants of the circle (90 degree arcs)
|
||||
*
|
||||
* [315, 360] && [0, 45) -> touchHints[0] = "Move Fingerprint to the left"
|
||||
* [45, 135) -> touchHints[1] = "Move Fingerprint down"
|
||||
* And so on.
|
||||
*/
|
||||
fun onTouchOutsideOfSensorAreaImpl(
|
||||
touchX: Float,
|
||||
touchY: Float,
|
||||
sensorX: Float,
|
||||
sensorY: Float,
|
||||
rotation: Int
|
||||
): String {
|
||||
val touchHints =
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
|
||||
val xRelativeToSensor = touchX - sensorX
|
||||
// Touch coordinates are with respect to the upper left corner, so reverse
|
||||
// this calculation
|
||||
val yRelativeToSensor = sensorY - touchY
|
||||
|
||||
var angleInRad =
|
||||
Math.atan2(yRelativeToSensor.toDouble(), xRelativeToSensor.toDouble())
|
||||
// If the radians are negative, that means we are counting clockwise.
|
||||
// So we need to add 360 degrees
|
||||
if (angleInRad < 0.0) {
|
||||
angleInRad += 2.0 * Math.PI
|
||||
}
|
||||
// rad to deg conversion
|
||||
val degrees = Math.toDegrees(angleInRad)
|
||||
|
||||
val degreesPerBucket = 360.0 / touchHints.size
|
||||
val halfBucketDegrees = degreesPerBucket / 2.0
|
||||
// The mapping should be as follows
|
||||
// [315, 360] && [0, 45] -> 0
|
||||
// [45, 135] -> 1
|
||||
var index = (((degrees + halfBucketDegrees) % 360) / degreesPerBucket).toInt()
|
||||
index %= touchHints.size
|
||||
|
||||
// A rotation of 90 degrees corresponds to increasing the index by 1.
|
||||
if (rotation == Surface.ROTATION_90) {
|
||||
index = (index + 1) % touchHints.size
|
||||
}
|
||||
|
||||
if (rotation == Surface.ROTATION_270) {
|
||||
index = (index + 3) % touchHints.size
|
||||
}
|
||||
|
||||
return touchHints[index]
|
||||
}
|
||||
|
||||
/** Cancel this request. */
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
package com.android.systemui.biometrics
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.android.systemui.R
|
||||
|
||||
/**
|
||||
* View corresponding with udfps_fpm_empty_view.xml
|
||||
@@ -32,4 +36,13 @@ class UdfpsFpmEmptyView(
|
||||
private val fingerprintDrawable: UdfpsFpDrawable = UdfpsFpDrawable(context)
|
||||
|
||||
override fun getDrawable(): UdfpsDrawable = fingerprintDrawable
|
||||
|
||||
fun updateAccessibilityViewLocation(sensorBounds: Rect) {
|
||||
val fingerprintAccessibilityView: View = findViewById(R.id.udfps_enroll_accessibility_view)
|
||||
val params: ViewGroup.LayoutParams = fingerprintAccessibilityView.layoutParams
|
||||
params.width = sensorBounds.width()
|
||||
params.height = sensorBounds.height()
|
||||
fingerprintAccessibilityView.layoutParams = params
|
||||
fingerprintAccessibilityView.requestLayout()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import android.view.MotionEvent
|
||||
import android.view.WindowManager
|
||||
import android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.systemui.CoreStartable
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.dagger.qualifiers.Main
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.graphics.RectF
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.widget.FrameLayout
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
|
||||
private const val TAG = "UdfpsOverlayView"
|
||||
private const val POINT_SIZE = 10f
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.MotionEvent
|
||||
import android.widget.FrameLayout
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.doze.DozeReceiver
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.systemui.biometrics.dagger
|
||||
|
||||
import com.android.settingslib.udfps.UdfpsUtils
|
||||
import com.android.systemui.biometrics.data.repository.PromptRepository
|
||||
import com.android.systemui.biometrics.data.repository.PromptRepositoryImpl
|
||||
import com.android.systemui.biometrics.domain.interactor.CredentialInteractor
|
||||
@@ -54,6 +55,9 @@ interface BiometricsModule {
|
||||
@BiometricsBackground
|
||||
fun providesPluginExecutor(threadFactory: ThreadFactory): Executor =
|
||||
threadFactory.buildExecutorOnNewThread("biometrics")
|
||||
|
||||
@Provides
|
||||
fun providesUdfpsUtils(): UdfpsUtils = UdfpsUtils()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import android.util.RotationUtils
|
||||
import android.view.MotionEvent
|
||||
import android.view.MotionEvent.INVALID_POINTER_ID
|
||||
import android.view.Surface
|
||||
import com.android.systemui.biometrics.UdfpsOverlayParams
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.systemui.biometrics.udfps.TouchProcessorResult.Failure
|
||||
import com.android.systemui.biometrics.udfps.TouchProcessorResult.ProcessedTouch
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.android.systemui.biometrics.udfps
|
||||
|
||||
import android.view.MotionEvent
|
||||
import com.android.systemui.biometrics.UdfpsOverlayParams
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
|
||||
/**
|
||||
* Determines whether a finger entered or left the area of the under-display fingerprint sensor
|
||||
|
||||
@@ -85,6 +85,7 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.jank.InteractionJankMonitor;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.settingslib.udfps.UdfpsUtils;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.biometrics.domain.interactor.BiometricPromptCredentialInteractor;
|
||||
import com.android.systemui.biometrics.domain.interactor.LogContextInteractor;
|
||||
@@ -167,6 +168,8 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
private BiometricPromptCredentialInteractor mBiometricPromptCredentialInteractor;
|
||||
@Mock
|
||||
private CredentialViewModel mCredentialViewModel;
|
||||
@Mock
|
||||
private UdfpsUtils mUdfpsUtils;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mFpAuthenticatorsRegisteredCaptor;
|
||||
@@ -958,7 +961,7 @@ public class AuthControllerTest extends SysuiTestCase {
|
||||
mPanelInteractionDetector, mUserManager, mLockPatternUtils, mUdfpsLogger,
|
||||
mLogContextInteractor, () -> mBiometricPromptCredentialInteractor,
|
||||
() -> mCredentialViewModel, mInteractionJankMonitor, mHandler,
|
||||
mBackgroundExecutor, mVibratorHelper);
|
||||
mBackgroundExecutor, mVibratorHelper, mUdfpsUtils);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,6 +38,8 @@ import android.view.WindowManager
|
||||
import android.view.accessibility.AccessibilityManager
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.keyguard.KeyguardUpdateMonitor
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.settingslib.udfps.UdfpsUtils
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator
|
||||
@@ -110,6 +112,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
@Mock private lateinit var featureFlags: FeatureFlags
|
||||
@Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
|
||||
@Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
||||
@Mock private lateinit var udfpsUtils: UdfpsUtils
|
||||
@Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
|
||||
|
||||
private val onTouch = { _: View, _: MotionEvent, _: Boolean -> true }
|
||||
@@ -144,7 +147,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
configurationController, keyguardStateController, unlockedScreenOffAnimationController,
|
||||
udfpsDisplayMode, secureSettings, REQUEST_ID, reason,
|
||||
controllerCallback, onTouch, activityLaunchAnimator, featureFlags,
|
||||
primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable
|
||||
primaryBouncerInteractor, alternateBouncerInteractor, isDebuggable, udfpsUtils
|
||||
)
|
||||
block()
|
||||
}
|
||||
@@ -400,109 +403,6 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
|
||||
assertThat(controllerOverlay.matchesRequestId(REQUEST_ID)).isTrue()
|
||||
assertThat(controllerOverlay.matchesRequestId(REQUEST_ID + 1)).isFalse()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testTouchOutsideAreaNoRotation() = withReason(REASON_ENROLL_ENROLLING) {
|
||||
val touchHints =
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
val rotation = Surface.ROTATION_0
|
||||
// touch at 0 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[0])
|
||||
// touch at 90 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[1])
|
||||
// touch at 180 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[2])
|
||||
// touch at 270 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[3])
|
||||
}
|
||||
|
||||
fun testTouchOutsideAreaNoRotation90Degrees() = withReason(REASON_ENROLL_ENROLLING) {
|
||||
val touchHints =
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
val rotation = Surface.ROTATION_90
|
||||
// touch at 0 degrees -> 90 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[1])
|
||||
// touch at 90 degrees -> 180 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[2])
|
||||
// touch at 180 degrees -> 270 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[3])
|
||||
// touch at 270 degrees -> 0 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[0])
|
||||
}
|
||||
|
||||
fun testTouchOutsideAreaNoRotation270Degrees() = withReason(REASON_ENROLL_ENROLLING) {
|
||||
val touchHints =
|
||||
context.resources.getStringArray(R.array.udfps_accessibility_touch_hints)
|
||||
val rotation = Surface.ROTATION_270
|
||||
// touch at 0 degrees -> 270 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[3])
|
||||
// touch at 90 degrees -> 0 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, -1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[0])
|
||||
// touch at 180 degrees -> 90 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
-1.0f /* x */, 0.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[1])
|
||||
// touch at 270 degrees -> 180 degrees
|
||||
assertThat(
|
||||
controllerOverlay.onTouchOutsideOfSensorAreaImpl(
|
||||
0.0f /* x */, 1.0f /* y */,
|
||||
0.0f /* sensorX */, 0.0f /* sensorY */, rotation
|
||||
)
|
||||
).isEqualTo(touchHints[2])
|
||||
}
|
||||
}
|
||||
|
||||
private class EnrollListener(
|
||||
|
||||
@@ -71,6 +71,8 @@ import androidx.test.filters.SmallTest;
|
||||
import com.android.internal.logging.InstanceIdSequence;
|
||||
import com.android.internal.util.LatencyTracker;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams;
|
||||
import com.android.settingslib.udfps.UdfpsUtils;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
import com.android.systemui.animation.ActivityLaunchAnimator;
|
||||
@@ -230,10 +232,12 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
private ScreenLifecycle.Observer mScreenObserver;
|
||||
private FingerprintSensorPropertiesInternal mOpticalProps;
|
||||
private FingerprintSensorPropertiesInternal mUltrasonicProps;
|
||||
private UdfpsUtils mUdfpsUtils;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
Execution execution = new FakeExecution();
|
||||
mUdfpsUtils = new UdfpsUtils();
|
||||
|
||||
when(mLayoutInflater.inflate(R.layout.udfps_view, null, false))
|
||||
.thenReturn(mUdfpsView);
|
||||
@@ -305,7 +309,7 @@ public class UdfpsControllerTest extends SysuiTestCase {
|
||||
mUnlockedScreenOffAnimationController, mSystemUIDialogManager, mLatencyTracker,
|
||||
mActivityLaunchAnimator, alternateTouchProvider, mBiometricExecutor,
|
||||
mPrimaryBouncerInteractor, mSinglePointerTouchProcessor, mSessionTracker,
|
||||
mAlternateBouncerInteractor, mSecureSettings);
|
||||
mAlternateBouncerInteractor, mSecureSettings, mUdfpsUtils);
|
||||
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
|
||||
mOverlayController = mOverlayCaptor.getValue();
|
||||
verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.testing.ViewUtils
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Surface
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.systemui.R
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.util.mockito.any
|
||||
|
||||
@@ -23,8 +23,8 @@ import android.view.MotionEvent.PointerProperties
|
||||
import android.view.Surface
|
||||
import android.view.Surface.Rotation
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.settingslib.udfps.UdfpsOverlayParams
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.biometrics.UdfpsOverlayParams
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
||||
Reference in New Issue
Block a user