Update aod face-auth transition

Previously unlocking via face-auth on AoD (can be triggered
on a UDFPS failures on AoD), the transition had poor
scrim & light reveal animations.

Fixes: 232050211
Test: atest AuthRippleControllerTest ScrimControllerTest
Test: manual
Change-Id: I3d250794181841c0389e1e72cbbebb2e7378f217
This commit is contained in:
Beverly
2022-05-16 16:09:37 +00:00
committed by Beverly Tai
parent 986c517b77
commit 2b6edba838
5 changed files with 99 additions and 57 deletions

View File

@@ -23,7 +23,6 @@ import android.content.Context
import android.graphics.PointF
import android.hardware.biometrics.BiometricFingerprintConstants
import android.hardware.biometrics.BiometricSourceType
import android.util.DisplayMetrics
import android.util.Log
import androidx.annotation.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
@@ -46,7 +45,6 @@ import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.Cent
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.ViewController
import com.android.systemui.util.leak.RotationUtils
import java.io.PrintWriter
import javax.inject.Inject
import javax.inject.Provider
@@ -127,17 +125,37 @@ class AuthRippleController @Inject constructor(
}
updateSensorLocation()
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&
fingerprintSensorLocation != null) {
mView.setFingerprintSensorLocation(fingerprintSensorLocation!!, udfpsRadius)
showUnlockedRipple()
} else if (biometricSourceType == BiometricSourceType.FACE &&
faceSensorLocation != null) {
if (!bypassController.canBypass()) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
fingerprintSensorLocation?.let {
mView.setFingerprintSensorLocation(it, udfpsRadius)
circleReveal = CircleReveal(
it.x,
it.y,
0f,
Math.max(
Math.max(it.x, centralSurfaces.displayWidth - it.x),
Math.max(it.y, centralSurfaces.displayHeight - it.y)
)
)
showUnlockedRipple()
}
} else if (biometricSourceType == BiometricSourceType.FACE) {
if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) {
return
}
mView.setSensorLocation(faceSensorLocation!!)
showUnlockedRipple()
faceSensorLocation?.let {
mView.setSensorLocation(it)
circleReveal = CircleReveal(
it.x,
it.y,
0f,
Math.max(
Math.max(it.x, centralSurfaces.displayWidth - it.x),
Math.max(it.y, centralSurfaces.displayHeight - it.y)
)
)
showUnlockedRipple()
}
}
}
@@ -209,48 +227,8 @@ class AuthRippleController @Inject constructor(
}
fun updateSensorLocation() {
updateFingerprintLocation()
fingerprintSensorLocation = authController.fingerprintSensorLocation
faceSensorLocation = authController.faceAuthSensorLocation
fingerprintSensorLocation?.let {
circleReveal = CircleReveal(
it.x,
it.y,
0f,
Math.max(
Math.max(it.x, centralSurfaces.displayWidth - it.x),
Math.max(it.y, centralSurfaces.displayHeight - it.y)
)
)
}
}
private fun updateFingerprintLocation() {
val displayMetrics = DisplayMetrics()
sysuiContext.display?.getRealMetrics(displayMetrics)
val width = displayMetrics.widthPixels
val height = displayMetrics.heightPixels
authController.fingerprintSensorLocation?.let {
fingerprintSensorLocation = when (RotationUtils.getRotation(sysuiContext)) {
RotationUtils.ROTATION_LANDSCAPE -> {
val normalizedYPos: Float = it.y / width
val normalizedXPos: Float = it.x / height
PointF(width * normalizedYPos, height * (1 - normalizedXPos))
}
RotationUtils.ROTATION_UPSIDE_DOWN -> {
PointF(width - it.x, height - it.y)
}
RotationUtils.ROTATION_SEASCAPE -> {
val normalizedYPos: Float = it.y / width
val normalizedXPos: Float = it.x / height
PointF(width * (1 - normalizedYPos), height * normalizedXPos)
}
else -> {
// ROTATION_NONE
PointF(it.x, it.y)
}
}
}
}
private fun updateRippleColor() {
@@ -372,6 +350,7 @@ class AuthRippleController @Inject constructor(
showUnlockRipple(BiometricSourceType.FINGERPRINT)
}
"face" -> {
// note: only shows when about to proceed to the home screen
updateSensorLocation()
pw.println("face ripple sensorLocation=$faceSensorLocation")
showUnlockRipple(BiometricSourceType.FACE)

View File

@@ -3907,7 +3907,8 @@ public class CentralSurfacesImpl extends CoreStartable implements
mScrimController.transitionTo(ScrimState.AOD);
} else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) {
mScrimController.transitionTo(ScrimState.KEYGUARD);
} else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) {
} else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()
&& !unlocking) {
mScrimController.transitionTo(ScrimState.DREAMING);
} else {
mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);

View File

@@ -252,7 +252,7 @@ public enum ScrimState {
mBehindTint = Color.BLACK;
mBlankScreen = false;
if (previousState == ScrimState.AOD) {
if (mDisplayRequiresBlanking && previousState == ScrimState.AOD) {
// Set all scrims black, before they fade transparent.
updateScrimColor(mScrimInFront, 1f /* alpha */, Color.BLACK /* tint */);
updateScrimColor(mScrimBehind, 1f /* alpha */, Color.BLACK /* tint */);

View File

@@ -292,7 +292,7 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
@RunWithLooper(setAsMainLooper = true)
fun testAnimatorRunWhenWakeAndUnlock() {
fun testAnimatorRunWhenWakeAndUnlock_fingerprint() {
val fpsLocation = PointF(5f, 5f)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
@@ -308,6 +308,25 @@ class AuthRippleControllerTest : SysuiTestCase() {
controller.startLightRevealScrimOnKeyguardFadingAway)
}
@Test
@RunWithLooper(setAsMainLooper = true)
fun testAnimatorRunWhenWakeAndUnlock_faceUdfpsFingerDown() {
val faceLocation = PointF(5f, 5f)
`when`(authController.faceAuthSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.isKeyguardVisible).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
`when`(authController.isUdfpsFingerDown).thenReturn(true)
controller.showUnlockRipple(BiometricSourceType.FACE)
assertTrue("reveal didn't start on keyguardFadingAway",
controller.startLightRevealScrimOnKeyguardFadingAway)
`when`(keyguardStateController.isKeyguardFadingAway).thenReturn(true)
controller.onKeyguardFadingAwayChanged()
assertFalse("reveal triggers multiple times",
controller.startLightRevealScrimOnKeyguardFadingAway)
}
@Test
fun testUpdateRippleColor() {
controller.onViewAttached()

View File

@@ -831,7 +831,7 @@ public class ScrimControllerTest extends SysuiTestCase {
}
@Test
public void scrimBlanksWhenUnlockingFromPulse() {
public void scrimBlankCallbackWhenUnlockingFromPulse() {
boolean[] blanked = {false};
// Simulate unlock with fingerprint
mScrimController.transitionTo(ScrimState.PULSING);
@@ -844,7 +844,50 @@ public class ScrimControllerTest extends SysuiTestCase {
}
});
finishAnimationsImmediately();
Assert.assertTrue("Scrim should blank when unlocking from pulse.", blanked[0]);
Assert.assertTrue("Scrim should send display blanked callback when unlocking "
+ "from pulse.", blanked[0]);
}
@Test
public void blankingNotRequired_leavingAoD() {
// GIVEN display does NOT need blanking
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(false);
mScrimController = new ScrimController(mLightBarController,
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
mScreenOffAnimationController,
mPanelExpansionStateManager,
mKeyguardUnlockAnimationController,
mStatusBarKeyguardViewManager);
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
mScrimController.setAnimatorListener(mAnimatorListener);
mScrimController.setHasBackdrop(false);
mScrimController.setWallpaperSupportsAmbientMode(false);
mScrimController.transitionTo(ScrimState.KEYGUARD);
finishAnimationsImmediately();
// WHEN Simulate unlock with fingerprint
mScrimController.transitionTo(ScrimState.AOD);
finishAnimationsImmediately();
// WHEN transitioning to UNLOCKED, onDisplayCallbackBlanked callback called to continue
// the transition but the scrim was not actually blanked
mScrimController.transitionTo(ScrimState.UNLOCKED,
new ScrimController.Callback() {
@Override
public void onDisplayBlanked() {
// Front scrim should not be black nor opaque
Assert.assertTrue("Scrim should NOT be visible during transition."
+ " Alpha: " + mScrimInFront.getViewAlpha(),
mScrimInFront.getViewAlpha() == 0f);
Assert.assertSame("Scrim should not be visible during transition.",
mScrimVisibility, TRANSPARENT);
}
});
finishAnimationsImmediately();
}
@Test