Loading packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +31 −52 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -127,19 +125,39 @@ class AuthRippleController @Inject constructor( } updateSensorLocation() if (biometricSourceType == BiometricSourceType.FINGERPRINT && fingerprintSensorLocation != null) { mView.setFingerprintSensorLocation(fingerprintSensorLocation!!, udfpsRadius) 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 && faceSensorLocation != null) { if (!bypassController.canBypass()) { } } else if (biometricSourceType == BiometricSourceType.FACE) { if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) { return } mView.setSensorLocation(faceSensorLocation!!) 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() } } } private fun showUnlockedRipple() { notificationShadeWindowController.setForcePluginOpen(true, this) Loading Loading @@ -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() { Loading Loading @@ -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) Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +2 −1 Original line number Diff line number Diff line Loading @@ -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); Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 */); Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt +20 −1 Original line number Diff line number Diff line Loading @@ -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() Loading @@ -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() Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +45 −2 Original line number Diff line number Diff line Loading @@ -833,7 +833,7 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test public void scrimBlanksWhenUnlockingFromPulse() { public void scrimBlankCallbackWhenUnlockingFromPulse() { boolean[] blanked = {false}; // Simulate unlock with fingerprint mScrimController.transitionTo(ScrimState.PULSING); Loading @@ -846,7 +846,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 Loading Loading
packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +31 −52 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading Loading @@ -127,19 +125,39 @@ class AuthRippleController @Inject constructor( } updateSensorLocation() if (biometricSourceType == BiometricSourceType.FINGERPRINT && fingerprintSensorLocation != null) { mView.setFingerprintSensorLocation(fingerprintSensorLocation!!, udfpsRadius) 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 && faceSensorLocation != null) { if (!bypassController.canBypass()) { } } else if (biometricSourceType == BiometricSourceType.FACE) { if (!bypassController.canBypass() && !authController.isUdfpsFingerDown) { return } mView.setSensorLocation(faceSensorLocation!!) 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() } } } private fun showUnlockedRipple() { notificationShadeWindowController.setForcePluginOpen(true, this) Loading Loading @@ -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() { Loading Loading @@ -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) Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +2 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +1 −1 Original line number Diff line number Diff line Loading @@ -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 */); Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt +20 −1 Original line number Diff line number Diff line Loading @@ -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() Loading @@ -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() Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +45 −2 Original line number Diff line number Diff line Loading @@ -833,7 +833,7 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test public void scrimBlanksWhenUnlockingFromPulse() { public void scrimBlankCallbackWhenUnlockingFromPulse() { boolean[] blanked = {false}; // Simulate unlock with fingerprint mScrimController.transitionTo(ScrimState.PULSING); Loading @@ -846,7 +846,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 Loading