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:
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */);
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user