Fix errant bouncer/keyboard display over keyguard

Legacy logic attempts to infer whether the bouncer should show based
upon panel expansion events in a variety of scenarios.

Modify the logic a bit to require show() be called on the bouncer, in
order for any events to be forwarded.

Fixes: 260589442
Fixes: 260310219
Test: atest StatusBarKeyguardViewManager
Test: manual - Bouncer works for SIM, from AOD, from UDFPS, over
occluded activity, while unlocked, over dreams, with face auth,
tapping on notif

Change-Id: I4e5919d222c1c94731dc5bf050ff66a8376b38a9
This commit is contained in:
Matt Pietal
2022-12-02 15:16:18 +00:00
parent 1a38ab1cc0
commit d49175bc73
2 changed files with 72 additions and 87 deletions

View File

@@ -19,9 +19,6 @@ package com.android.systemui.statusbar.phone;
import static android.view.WindowInsets.Type.navigationBars;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_DISMISS_BOUNCER;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_SHOW_BOUNCER;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_UNLOCK_COLLAPSING;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
@@ -140,6 +137,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private final BouncerView mPrimaryBouncerView;
private final Lazy<com.android.systemui.shade.ShadeController> mShadeController;
// Local cache of expansion events, to avoid duplicates
private float mFraction = -1f;
private boolean mTracking = false;
private final PrimaryBouncerExpansionCallback mExpansionCallback =
new PrimaryBouncerExpansionCallback() {
private boolean mPrimaryBouncerAnimating;
@@ -440,80 +441,68 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
hideBouncer(true /* destroyView */);
}
@Override
public void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
float fraction = event.getFraction();
boolean tracking = event.getTracking();
private boolean beginShowingBouncer(ShadeExpansionChangeEvent event) {
// Avoid having the shade and the bouncer open at the same time over a dream.
final boolean hideBouncerOverDream =
mDreamOverlayStateController.isOverlayActive()
&& (mNotificationPanelViewController.isExpanded()
|| mNotificationPanelViewController.isExpanding());
// We don't want to translate the bounce when:
// • device is dozing and not pulsing
// • Keyguard is occluded, because we're in a FLAG_SHOW_WHEN_LOCKED activity and need to
// conserve the original animation.
// • The user quickly taps on the display and we show "swipe up to unlock."
// • Keyguard will be dismissed by an action. a.k.a: FLAG_DISMISS_KEYGUARD_ACTIVITY
// • Full-screen user switcher is displayed.
if (mDozing && !mPulsing) {
final boolean isUserTrackingStarted =
event.getFraction() != KeyguardBouncer.EXPANSION_HIDDEN && event.getTracking();
return mKeyguardStateController.isShowing()
&& !primaryBouncerIsOrWillBeShowing()
&& isUserTrackingStarted
&& !hideBouncerOverDream
&& !mKeyguardStateController.isOccluded()
&& !mKeyguardStateController.canDismissLockScreen()
&& !bouncerIsAnimatingAway()
&& !mNotificationPanelViewController.isUnlockHintRunning()
&& !(mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED);
}
@Override
public void onPanelExpansionChanged(ShadeExpansionChangeEvent event) {
float fraction = event.getFraction();
boolean tracking = event.getTracking();
if (mFraction == fraction && mTracking == tracking) {
// Ignore duplicate events, as they will cause confusion with bouncer expansion
return;
} else if (mNotificationPanelViewController.isUnlockHintRunning()) {
}
mFraction = fraction;
mTracking = tracking;
/*
* The bouncer may have received a call to show(), or the following will infer it from
* device state and touch handling. The bouncer MUST have been notified that it is about to
* show if any subsequent events are to be handled.
*/
if (beginShowingBouncer(event)) {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
} else {
mPrimaryBouncerInteractor.show(/* isScrimmed= */false);
}
}
if (!primaryBouncerIsOrWillBeShowing()) {
return;
}
if (mKeyguardStateController.isShowing()) {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setExpansion(fraction);
} else {
mPrimaryBouncerInteractor.setPanelExpansion(fraction);
}
} else {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
} else {
mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
}
} else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) {
// Don't expand to the bouncer. Instead transition back to the lock screen (see
// CentralSurfaces#showBouncerOrLockScreenIfKeyguard)
return;
} else if (mKeyguardStateController.isOccluded()
&& !mDreamOverlayStateController.isOverlayActive()) {
return;
} else if (needsFullscreenBouncer()) {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
} else {
mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_VISIBLE);
}
} else if (mKeyguardStateController.isShowing() && !hideBouncerOverDream) {
if (!isWakeAndUnlocking()
&& !(mBiometricUnlockController.getMode() == MODE_DISMISS_BOUNCER)
&& !(mBiometricUnlockController.getMode() == MODE_SHOW_BOUNCER)
&& !isUnlockCollapsing()) {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setExpansion(fraction);
} else {
mPrimaryBouncerInteractor.setPanelExpansion(fraction);
}
}
if (fraction != KeyguardBouncer.EXPANSION_HIDDEN && tracking
&& !mKeyguardStateController.canDismissLockScreen()
&& !primaryBouncerIsShowing()
&& !bouncerIsAnimatingAway()) {
if (mPrimaryBouncer != null) {
mPrimaryBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
} else {
mPrimaryBouncerInteractor.show(/* isScrimmed= */false);
}
}
} else if (!mKeyguardStateController.isShowing() && isPrimaryBouncerInTransit()) {
// Keyguard is not visible anymore, but expansion animation was still running.
// We need to hide the bouncer, otherwise it will be stuck in transit.
if (mPrimaryBouncer != null) {
mPrimaryBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
} else {
mPrimaryBouncerInteractor.setPanelExpansion(KeyguardBouncer.EXPANSION_HIDDEN);
}
} else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) {
// Panel expanded while pulsing but didn't translate the bouncer (because we are
// unlocked.) Let's simply wake-up to dismiss the lock screen.
mCentralSurfaces.wakeUpIfDozing(
SystemClock.uptimeMillis(),
mCentralSurfaces.getBouncerContainer(),
"BOUNCER_VISIBLE");
}
}
@@ -704,11 +693,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return mode == MODE_WAKE_AND_UNLOCK || mode == MODE_WAKE_AND_UNLOCK_PULSING;
}
private boolean isUnlockCollapsing() {
int mode = mBiometricUnlockController.getMode();
return mode == MODE_UNLOCK_COLLAPSING;
}
/**
* Adds a {@param runnable} to be executed after Keyguard is gone.
*/

View File

@@ -221,32 +221,33 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
verify(mPrimaryBouncer).show(anyBoolean(), eq(true));
}
@Test
public void onPanelExpansionChanged_neverHidesFullscreenBouncer() {
when(mPrimaryBouncer.isShowing()).thenReturn(true);
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
KeyguardSecurityModel.SecurityMode.SimPuk);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_VISIBLE));
reset(mPrimaryBouncer);
when(mKeyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(
KeyguardSecurityModel.SecurityMode.SimPin);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_VISIBLE));
}
@Test
public void onPanelExpansionChanged_neverShowsDuringHintAnimation() {
when(mNotificationPanelView.isUnlockHintRunning()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer).setExpansion(eq(KeyguardBouncer.EXPANSION_HIDDEN));
verify(mPrimaryBouncer, never()).setExpansion(anyFloat());
}
@Test
public void onPanelExpansionChanged_propagatesToBouncer() {
public void onPanelExpansionChanged_propagatesToBouncerOnlyIfShowing() {
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer, never()).setExpansion(eq(0.5f));
when(mPrimaryBouncer.isShowing()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(
expansionEvent(/* fraction= */ 0.6f, /* expanded= */ false, /* tracking= */ true));
verify(mPrimaryBouncer).setExpansion(eq(0.6f));
}
@Test
public void onPanelExpansionChanged_duplicateEventsAreIgnored() {
when(mPrimaryBouncer.isShowing()).thenReturn(true);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer).setExpansion(eq(0.5f));
reset(mPrimaryBouncer);
mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
verify(mPrimaryBouncer, never()).setExpansion(eq(0.5f));
}
@Test