From e4cb6c8a31585de27afe89b1c06e1a5a124d8c66 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Wed, 19 Jul 2017 18:08:07 +0200 Subject: [PATCH] Flicker free screen-on from AOD When pulsing from AOD, we force the display OFF first. This allows us to transition smoothly from AOD. Also, we add a scrim transition for whenever we are waking up from dozing. This relies on I4f3a863709a970f0fc8682c0a0c3547886e1fd0f which forces the DOZE -> ON transition through OFF first. Also fixes the WAKE_AND_UNLOCK transition that happens when waking up with the fingerprint sensor. Also fix an issue where KeyguardViewMediator's mWakeAndUnlocking was cleared in onScreenTurnedOff; this should have been added to the wakefulness lifecycle instead and now that the AOD -> ON transtion dispatches the screen off callback it broke the fingerprint unlock transition. Fixes: 35849781 Fixes: 63887857 Fixes: 63783651 Fixes: 63727166 Test: AOD, receive notification; AOD, unlock with fingerprint; AOD, wake to lockscreen. Verify that everything is flicker-free. Change-Id: I7d539db80a1c7e9216cf4c5c1e6d314c1893f12d --- .../android/systemui/doze/DozeMachine.java | 1 + .../keyguard/KeyguardViewMediator.java | 2 +- .../statusbar/phone/DozeScrimController.java | 5 +- .../phone/FingerprintUnlockController.java | 2 +- .../statusbar/phone/ScrimController.java | 48 +++++++++++++++++-- .../systemui/statusbar/phone/StatusBar.java | 25 ++++++++-- .../systemui/doze/DozeScreenStateTest.java | 4 +- 7 files changed, 73 insertions(+), 14 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index 0be4eda8a069e..a1dfeb34a6707 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -91,6 +91,7 @@ public class DozeMachine { case UNINITIALIZED: case INITIALIZED: case DOZE: + case DOZE_REQUEST_PULSE: case DOZE_AOD_PAUSED: return Display.STATE_OFF; case DOZE_PULSING: diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 6d10d9413e664..e23875f6c094e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -811,6 +811,7 @@ public class KeyguardViewMediator extends SystemUI { synchronized (this) { mDeviceInteractive = false; mGoingToSleep = false; + mWakeAndUnlocking = false; resetKeyguardDonePendingLocked(); mHideAnimationRun = false; @@ -1957,7 +1958,6 @@ public class KeyguardViewMediator extends SystemUI { if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff"); mStatusBarKeyguardViewManager.onScreenTurnedOff(); mDrawnCallback = null; - mWakeAndUnlocking = false; } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java index f591524979399..2dc467f2add15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java @@ -114,6 +114,7 @@ public class DozeScrimController { // be invoked when we're done so that the caller can drop the pulse wakelock. mPulseCallback = callback; mPulseReason = reason; + mScrimController.setDozeInFrontAlpha(1f); mHandler.post(mPulseIn); } @@ -290,10 +291,6 @@ public class DozeScrimController { // Signal that the pulse is ready to turn the screen on and draw. pulseStarted(); - - if (mDozeParameters.getAlwaysOn()) { - mHandler.post(DozeScrimController.this::onScreenTurnedOn); - } } }; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java index 5af80f546f48b..df059e3686ba6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java @@ -285,7 +285,7 @@ public class FingerprintUnlockController extends KeyguardUpdateMonitorCallback { if (!mUpdateMonitor.isDeviceInteractive()) { if (!mStatusBarKeyguardViewManager.isShowing()) { return MODE_ONLY_WAKE; - } else if (pulsingOrAod() && unlockingAllowed) { + } else if (mDozeScrimController.isPulsing() && unlockingAllowed) { return MODE_WAKE_AND_UNLOCK_PULSING; } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) { return MODE_WAKE_AND_UNLOCK; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index a8b1c91fc2358..62d4b736d93a1 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -25,7 +25,6 @@ import android.content.Context; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.util.Log; import android.util.MathUtils; import android.view.View; import android.view.ViewGroup; @@ -120,6 +119,12 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, private boolean mKeyguardFadingOutInProgress; private boolean mAnimatingDozeUnlock; private ValueAnimator mKeyguardFadeoutAnimation; + /** Wake up from AOD transition is starting; need fully opaque front scrim */ + private boolean mWakingUpFromAodStarting; + /** Wake up from AOD transition is in progress; need black tint */ + private boolean mWakingUpFromAodInProgress; + /** Wake up from AOD transition is animating; need to reset when animation finishes */ + private boolean mWakingUpFromAodAnimationRunning; public ScrimController(LightBarController lightBarController, ScrimView scrimBehind, ScrimView scrimInFront, View headsUpScrim) { @@ -187,9 +192,32 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, scheduleUpdate(); } + public void prepareWakeUpFromAod() { + mWakingUpFromAodInProgress = true; + mWakingUpFromAodStarting = true; + mAnimateChange = false; + scheduleUpdate(); + onPreDraw(); + } + + public void wakeUpFromAod() { + if (mWakeAndUnlocking || mAnimateKeyguardFadingOut) { + // Wake and unlocking has a separate transition that must not be interfered with. + mWakingUpFromAodStarting = false; + return; + } + if (mWakingUpFromAodStarting) { + mWakingUpFromAodInProgress = true; + mWakingUpFromAodStarting = false; + mAnimateChange = true; + scheduleUpdate(); + } + } + public void setWakeAndUnlocking() { mWakeAndUnlocking = true; mAnimatingDozeUnlock = true; + mWakingUpFromAodStarting = false; scheduleUpdate(); } @@ -356,7 +384,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, setScrimBehindAlpha(mScrimBehindAlpha); } else { float fraction = Math.max(0, Math.min(mFraction, 1)); - setScrimInFrontAlpha(0f); + if (mWakingUpFromAodStarting) { + setScrimInFrontAlpha(1f); + } else { + setScrimInFrontAlpha(0f); + } setScrimBehindAlpha(fraction * (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking) + mScrimBehindAlphaUnlocking); @@ -426,7 +458,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, scrimView.setViewAlpha(alpha); int dozeTint = Color.TRANSPARENT; - if (mAnimatingDozeUnlock || mDozing) { + + boolean dozing = mAnimatingDozeUnlock || mDozing; + boolean frontScrimDozing = mWakingUpFromAodInProgress; + if (dozing || frontScrimDozing && scrim == mScrimInFront) { dozeTint = Color.BLACK; } scrimView.setTint(dozeTint); @@ -458,6 +493,10 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mKeyguardFadingOutInProgress = false; mAnimatingDozeUnlock = false; } + if (mWakingUpFromAodAnimationRunning) { + mWakingUpFromAodAnimationRunning = false; + mWakingUpFromAodInProgress = false; + } scrim.setTag(TAG_KEY_ANIM, null); scrim.setTag(TAG_KEY_ANIM_TARGET, null); } @@ -467,6 +506,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mKeyguardFadingOutInProgress = true; mKeyguardFadeoutAnimation = anim; } + if (mWakingUpFromAodInProgress) { + mWakingUpFromAodAnimationRunning = true; + } if (mSkipFirstFrame) { anim.setCurrentPlayTime(16); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index e90d1c1e27b55..9e1a2a2b5ffd2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -21,6 +21,9 @@ import static android.app.StatusBarManager.WINDOW_STATE_SHOWING; import static android.app.StatusBarManager.windowStateToString; import static android.content.res.Configuration.UI_MODE_TYPE_CAR; +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP; +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE; +import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING; import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT; import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT; @@ -4208,13 +4211,16 @@ public class StatusBar extends SystemUI implements DemoMode, } private boolean updateIsKeyguard() { + boolean wakeAndUnlocking = mFingerprintUnlockController.getMode() + == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; + // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise // there's no surface we can show to the user. Note that the device goes fully interactive // late in the transition, so we also allow the device to start dozing once the screen has // turned off fully. boolean keyguardForDozing = mDozingRequested && (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard)); - boolean shouldBeKeyguard = mKeyguardRequested || keyguardForDozing; + boolean shouldBeKeyguard = (mKeyguardRequested || keyguardForDozing) && !wakeAndUnlocking; if (keyguardForDozing) { updatePanelExpansionForKeyguard(); } @@ -4256,7 +4262,8 @@ public class StatusBar extends SystemUI implements DemoMode, } private void updatePanelExpansionForKeyguard() { - if (mState == StatusBarState.KEYGUARD) { + if (mState == StatusBarState.KEYGUARD && mFingerprintUnlockController.getMode() + != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) { instantExpandNotificationsPanel(); } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) { instantCollapseNotificationPanel(); @@ -5156,6 +5163,13 @@ public class StatusBar extends SystemUI implements DemoMode, public void onScreenTurningOn() { mFalsingManager.onScreenTurningOn(); mNotificationPanel.onScreenTurningOn(); + + int wakefulness = mWakefulnessLifecycle.getWakefulness(); + if (mDozing && (wakefulness == WAKEFULNESS_WAKING + || wakefulness == WAKEFULNESS_ASLEEP) && !isPulsing()) { + mScrimController.prepareWakeUpFromAod(); + } + if (mLaunchCameraOnScreenTurningOn) { mNotificationPanel.launchCamera(false, mLastCameraLaunchSource); mLaunchCameraOnScreenTurningOn = false; @@ -5164,13 +5178,18 @@ public class StatusBar extends SystemUI implements DemoMode, @Override public void onScreenTurnedOn() { + mScrimController.wakeUpFromAod(); mDozeScrimController.onScreenTurnedOn(); } @Override public void onScreenTurnedOff() { mFalsingManager.onScreenOff(); - updateIsKeyguard(); + // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard + // in that case destroys the HeadsUpManager state, so don't do it in that case. + if (!isPulsing()) { + updateIsKeyguard(); + } } }; diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 203876b9a2f52..e54c7924fc666 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -86,13 +86,13 @@ public class DozeScreenStateTest extends SysuiTestCase { } @Test - public void testScreen_onInRequestPulseWithAoD() { + public void testScreen_offInRequestPulseWithAoD() { mScreen.transitionTo(UNINITIALIZED, INITIALIZED); mScreen.transitionTo(INITIALIZED, DOZE_AOD); mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE); - assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState); + assertEquals(Display.STATE_OFF, mServiceFake.screenState); } } \ No newline at end of file