diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index f22c139b34ea6..969576082b362 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -155,7 +155,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable * gap is drawn between them). In this case we don't want to round their corners. */ private static final int DISTANCE_BETWEEN_ADJACENT_SECTIONS_PX = 1; - private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider; + private boolean mKeyguardBypassEnabled; private ExpandHelper mExpandHelper; private NotificationSwipeHelper mSwipeHelper; @@ -649,13 +649,21 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable inflateFooterView(); } + /** + * Sets whether keyguard bypass is enabled. If true, this layout will be rendered in bypass + * mode when it is on the keyguard. + */ + public void setKeyguardBypassEnabled(boolean isEnabled) { + mKeyguardBypassEnabled = isEnabled; + } + /** * @return the height at which we will wake up when pulsing */ public float getWakeUpHeight() { ExpandableView firstChild = getFirstChildWithBackground(); if (firstChild != null) { - if (mKeyguardBypassEnabledProvider.getBypassEnabled()) { + if (mKeyguardBypassEnabled) { return firstChild.getHeadsUpHeightWithoutHeader(); } else { return firstChild.getCollapsedHeight(); @@ -783,7 +791,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } } boolean shouldDrawBackground; - if (mKeyguardBypassEnabledProvider.getBypassEnabled() && onKeyguard()) { + if (mKeyguardBypassEnabled && onKeyguard()) { shouldDrawBackground = isPulseExpanding(); } else { shouldDrawBackground = !mAmbientState.isDozing() || anySectionHasVisibleChild; @@ -898,15 +906,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } private void reinitView() { - initView(getContext(), mKeyguardBypassEnabledProvider, mSwipeHelper); + initView(getContext(), mSwipeHelper); } @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) - void initView(Context context, - KeyguardBypassEnabledProvider keyguardBypassEnabledProvider, - NotificationSwipeHelper swipeHelper) { + void initView(Context context, NotificationSwipeHelper swipeHelper) { mScroller = new OverScroller(getContext()); - mKeyguardBypassEnabledProvider = keyguardBypassEnabledProvider; mSwipeHelper = swipeHelper; setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); @@ -1346,7 +1351,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable private void notifyAppearChangedListeners() { float appear; float expandAmount; - if (mKeyguardBypassEnabledProvider.getBypassEnabled() && onKeyguard()) { + if (mKeyguardBypassEnabled && onKeyguard()) { appear = calculateAppearFractionBypass(); expandAmount = getPulseHeight(); } else { @@ -2384,8 +2389,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable minTopPosition = firstVisibleSection.getBounds().top; } boolean shiftPulsingWithFirst = mNumHeadsUp <= 1 - && (mAmbientState.isDozing() - || (mKeyguardBypassEnabledProvider.getBypassEnabled() && onKeyguard)); + && (mAmbientState.isDozing() || (mKeyguardBypassEnabled && onKeyguard)); for (NotificationSection section : mSections) { int minBottomPosition = minTopPosition; if (section == lastSection) { @@ -2528,7 +2532,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable } else { mTopPaddingOverflow = 0; } - setTopPadding(topPadding, animate && !mKeyguardBypassEnabledProvider.getBypassEnabled()); + setTopPadding(topPadding, animate && !mKeyguardBypassEnabled); setExpandedHeight(mExpandedHeight); } @@ -3092,7 +3096,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable boolean performDisappearAnimation = !mIsExpanded // Only animate if we still have pinned heads up, otherwise we just have the // regular collapse animation of the lock screen - || (mKeyguardBypassEnabledProvider.getBypassEnabled() && onKeyguard() + || (mKeyguardBypassEnabled && onKeyguard() && mInHeadsUpPinnedMode); if (performDisappearAnimation && !isHeadsUp) { type = row.wasJustClicked() @@ -4315,7 +4319,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable // Since we are clipping to the outline we need to make sure that the shadows aren't // clipped when pulsing float ownTranslationZ = 0; - if (mKeyguardBypassEnabledProvider.getBypassEnabled() && mAmbientState.isHiddenAtAll()) { + if (mKeyguardBypassEnabled && mAmbientState.isHiddenAtAll()) { ExpandableView firstChildNotGone = getFirstChildNotGone(); if (firstChildNotGone != null && firstChildNotGone.showingPulsing()) { ownTranslationZ = firstChildNotGone.getTranslationZ(); @@ -5138,7 +5142,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable */ public float setPulseHeight(float height) { mAmbientState.setPulseHeight(height); - if (mKeyguardBypassEnabledProvider.getBypassEnabled()) { + if (mKeyguardBypassEnabled) { notifyAppearChangedListeners(); } requestChildrenUpdate(); @@ -6069,10 +6073,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable /** Only rows where entry.isHighPriority() is false. */ public static final int ROWS_GENTLE = 2; - interface KeyguardBypassEnabledProvider { - boolean getBypassEnabled(); - } - interface DismissListener { void onDismiss(@SelectedRows int selectedRows); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java index a92682a76a9ca..f861e53b2612d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java @@ -708,8 +708,10 @@ public class NotificationStackScrollLayoutController { }); } - mView.initView(mView.getContext(), mKeyguardBypassController::getBypassEnabled, - mSwipeHelper); + mView.initView(mView.getContext(), mSwipeHelper); + mView.setKeyguardBypassEnabled(mKeyguardBypassController.getBypassEnabled()); + mKeyguardBypassController + .registerOnBypassStateChangedListener(mView::setKeyguardBypassEnabled); mHeadsUpManager.addListener(mOnHeadsUpChangedListener); mHeadsUpManager.setAnimationStateHandler(mView::setHeadsUpGoingAwayAnimationsAllowed); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index 2cb0a3a289019..99df3f18729e8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -43,6 +43,11 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr @BypassOverride private val bypassOverride: Int private var hasFaceFeature: Boolean private var pendingUnlock: PendingUnlock? = null + private val listeners = mutableListOf() + + private val faceAuthEnabledChangedCallback = object : KeyguardStateController.Callback { + override fun onFaceAuthEnabledChanged() = notifyListeners() + } @IntDef( FACE_UNLOCK_BYPASS_NO_OVERRIDE, @@ -83,7 +88,10 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } return enabled && mKeyguardStateController.isFaceAuthEnabled } - private set + private set(value) { + field = value + notifyListeners() + } var bouncerShowing: Boolean = false var altBouncerShowing: Boolean = false @@ -140,6 +148,8 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr }) } + private fun notifyListeners() = listeners.forEach { it.onBypassStateChanged(bypassEnabled) } + /** * Notify that the biometric unlock has happened. * @@ -223,6 +233,32 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr pw.println(" hasFaceFeature: $hasFaceFeature") } + /** Registers a listener for bypass state changes. */ + fun registerOnBypassStateChangedListener(listener: OnBypassStateChangedListener) { + val start = listeners.isEmpty() + listeners.add(listener) + if (start) { + mKeyguardStateController.addCallback(faceAuthEnabledChangedCallback) + } + } + + /** + * Unregisters a listener for bypass state changes, previous registered with + * [registerOnBypassStateChangedListener] + */ + fun unregisterOnBypassStateChangedListener(listener: OnBypassStateChangedListener) { + listeners.remove(listener) + if (listeners.isEmpty()) { + mKeyguardStateController.removeCallback(faceAuthEnabledChangedCallback) + } + } + + /** Listener for bypass state change events. */ + interface OnBypassStateChangedListener { + /** Invoked when bypass becomes enabled or disabled. */ + fun onBypassStateChanged(isEnabled: Boolean) + } + companion object { const val BYPASS_FADE_DURATION = 67 diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java index fcfc9670b8b0d..742b1ab697277 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateController.java @@ -245,5 +245,11 @@ public interface KeyguardStateController extends CallbackController { * animation. */ default void onKeyguardDismissAmountChanged() {} + + /** + * Triggered when face auth becomes available or unavailable. Value should be queried with + * {@link KeyguardStateController#isFaceAuthEnabled()}. + */ + default void onFaceAuthEnabledChanged() {} } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index b03df880f0baa..3f35063fea6d1 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -63,7 +63,6 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; import com.android.systemui.statusbar.notification.row.FooterView; -import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.KeyguardBypassEnabledProvider; import com.android.systemui.statusbar.phone.KeyguardBypassController; import com.android.systemui.statusbar.phone.ShadeController; import com.android.systemui.statusbar.phone.StatusBar; @@ -101,7 +100,6 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { @Mock private NotificationRemoteInputManager mRemoteInputManager; @Mock private RemoteInputController mRemoteInputController; @Mock private NotificationRoundnessManager mNotificationRoundnessManager; - @Mock private KeyguardBypassEnabledProvider mKeyguardBypassEnabledProvider; @Mock private KeyguardBypassController mBypassController; @Mock private NotificationSectionsManager mNotificationSectionsManager; @Mock private NotificationSection mNotificationSection; @@ -150,8 +148,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { mAmbientState, mFeatureFlags, mUnlockedScreenOffAnimationController); - mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider, - mNotificationSwipeHelper); + mStackScrollerInternal.initView(getContext(), mNotificationSwipeHelper); mStackScroller = spy(mStackScrollerInternal); mStackScroller.setShelfController(notificationShelfController); mStackScroller.setStatusBar(mBar);