diff --git a/packages/SystemUI/res/values-h650dp/dimens.xml b/packages/SystemUI/res/values-h800dp/dimens.xml similarity index 74% rename from packages/SystemUI/res/values-h650dp/dimens.xml rename to packages/SystemUI/res/values-h800dp/dimens.xml index 8a00953049789..6a0e880675dfb 100644 --- a/packages/SystemUI/res/values-h650dp/dimens.xml +++ b/packages/SystemUI/res/values-h800dp/dimens.xml @@ -1,5 +1,5 @@ - 32dp + + 76dp \ No newline at end of file diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index e12f7b7b1ef31..0b65c70c7ef18 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -443,8 +443,8 @@ 30dp - - 26dp + + 36dp 250dp 0.62 diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java index 474fc90a1c3f6..62b50044132e4 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardHostView.java @@ -149,7 +149,6 @@ public class KeyguardHostView extends FrameLayout implements SecurityCallback { mSecurityContainer.setLockPatternUtils(mLockPatternUtils); mSecurityContainer.setSecurityCallback(this); mSecurityContainer.showPrimarySecurityScreen(false); - // mSecurityContainer.updateSecurityViews(false /* not bouncing */); } /** diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java index 526e5fa78d355..e18ac74d44656 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java @@ -79,8 +79,8 @@ public class AnglesClassifier extends StrokeClassifier { @Override public float getFalseTouchEvaluation(int type, Stroke stroke) { Data data = mStrokeMap.get(stroke); - return AnglesVarianceEvaluator.evaluate(data.getAnglesVariance()) - + AnglesPercentageEvaluator.evaluate(data.getAnglesPercentage()); + return AnglesVarianceEvaluator.evaluate(data.getAnglesVariance(), type) + + AnglesPercentageEvaluator.evaluate(data.getAnglesPercentage(), type); } private static class Data { diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java index e6c42da361cc9..e6e42f2d0eeff 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java @@ -17,10 +17,11 @@ package com.android.systemui.classifier; public class AnglesPercentageEvaluator { - public static float evaluate(float value) { + public static float evaluate(float value, int type) { + final boolean secureUnlock = type == Classifier.BOUNCER_UNLOCK; float evaluation = 0.0f; - if (value < 1.00) evaluation++; - if (value < 0.90) evaluation++; + if (value < 1.00 && !secureUnlock) evaluation++; + if (value < 0.90 && !secureUnlock) evaluation++; if (value < 0.70) evaluation++; return evaluation; } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java index 99cc1a6d14fed..6883dd0af3d35 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceEvaluator.java @@ -17,14 +17,15 @@ package com.android.systemui.classifier; public class AnglesVarianceEvaluator { - public static float evaluate(float value) { + public static float evaluate(float value, int type) { + final boolean secureUnlock = type == Classifier.BOUNCER_UNLOCK; float evaluation = 0.0f; if (value > 0.05) evaluation++; if (value > 0.10) evaluation++; if (value > 0.20) evaluation++; - if (value > 0.40) evaluation++; - if (value > 0.80) evaluation++; - if (value > 1.50) evaluation++; + if (value > 0.40 && !secureUnlock) evaluation++; + if (value > 0.80 && !secureUnlock) evaluation++; + if (value > 1.50 && !secureUnlock) evaluation++; return evaluation; } } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java index cb761a9b13141..909896eb6c556 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/Classifier.java @@ -31,6 +31,7 @@ public abstract class Classifier { public static final int LEFT_AFFORDANCE = 5; public static final int RIGHT_AFFORDANCE = 6; public static final int GENERIC = 7; + public static final int BOUNCER_UNLOCK = 8; /** * Contains all the information about touch events from which the classifier can query diff --git a/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java index e20b1ca64580e..5f04222197ab7 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/DirectionEvaluator.java @@ -33,6 +33,7 @@ public class DirectionEvaluator { } break; case Classifier.UNLOCK: + case Classifier.BOUNCER_UNLOCK: if (!vertical || yDiff >= 0.0) { return falsingEvaluation; } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java index ed659e2d16d57..913e7819b7fae 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManager.java @@ -356,11 +356,12 @@ public class FalsingManager implements SensorEventListener { mDataCollector.setQsExpanded(expanded); } - public void onTrackingStarted() { + public void onTrackingStarted(boolean secure) { if (FalsingLog.ENABLED) { FalsingLog.i("onTrackingStarted", ""); } - mHumanInteractionClassifier.setType(Classifier.UNLOCK); + mHumanInteractionClassifier.setType(secure ? + Classifier.BOUNCER_UNLOCK : Classifier.UNLOCK); mDataCollector.onTrackingStarted(); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index 694026473dc0c..a1b17e4ef0ea4 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -83,6 +83,7 @@ import com.android.systemui.SystemUIFactory; import com.android.systemui.UiOffloadThread; import com.android.systemui.classifier.FalsingManager; import com.android.systemui.statusbar.phone.FingerprintUnlockController; +import com.android.systemui.statusbar.phone.NotificationPanelView; import com.android.systemui.statusbar.phone.StatusBar; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -2011,8 +2012,9 @@ public class KeyguardViewMediator extends SystemUI { } public StatusBarKeyguardViewManager registerStatusBar(StatusBar statusBar, - ViewGroup container, FingerprintUnlockController fingerprintUnlockController) { - mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, + ViewGroup container, NotificationPanelView panelView, + FingerprintUnlockController fingerprintUnlockController) { + mStatusBarKeyguardViewManager.registerStatusBar(statusBar, container, panelView, fingerprintUnlockController, mDismissCallbackRegistry); return mStatusBarKeyguardViewManager; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index edfbd3f8ec729..110995505444c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -20,6 +20,7 @@ import android.content.Context; import android.os.Handler; import android.os.UserHandle; import android.os.UserManager; +import android.util.MathUtils; import android.util.Slog; import android.util.StatsLog; import android.view.KeyEvent; @@ -49,7 +50,8 @@ import static com.android.keyguard.KeyguardSecurityModel.SecurityMode; */ public class KeyguardBouncer { - final static private String TAG = "KeyguardBouncer"; + private static final String TAG = "KeyguardBouncer"; + static final float ALPHA_EXPANSION_THRESHOLD = 0.95f; protected final Context mContext; protected final ViewMediatorCallback mCallback; @@ -86,13 +88,25 @@ public class KeyguardBouncer { } public void show(boolean resetSecuritySelection) { + show(resetSecuritySelection, true /* notifyFalsing */); + } + + public void show(boolean resetSecuritySelection, boolean notifyFalsing) { final int keyguardUserId = KeyguardUpdateMonitor.getCurrentUser(); if (keyguardUserId == UserHandle.USER_SYSTEM && UserManager.isSplitSystemUser()) { // In split system user mode, we never unlock system user. return; } - mFalsingManager.onBouncerShown(); ensureView(); + + // On the keyguard, we want to show the bouncer when the user drags up, but it's + // not correct to end the falsing session. We still need to verify if those touches + // are valid. + // Later, at the end of the animation, when the bouncer is at the top of the screen, + // onFullyShown() will be called and FalsingManager will stop recording touches. + if (notifyFalsing) { + mFalsingManager.onBouncerShown(); + } if (resetSecuritySelection) { // showPrimarySecurityScreen() updates the current security method. This is needed in // case we are already showing and the current security method changed. @@ -126,6 +140,28 @@ public class KeyguardBouncer { mCallback.onBouncerVisiblityChanged(true /* shown */); } + /** + * This method must be called at the end of the bouncer animation when + * the translation is performed manually by the user, otherwise FalsingManager + * will never be notified and its internal state will be out of sync. + */ + public void onFullyShown() { + mFalsingManager.onBouncerShown(); + } + + /** + * This method must be called at the end of the bouncer animation when + * the translation is performed manually by the user, otherwise FalsingManager + * will never be notified and its internal state will be out of sync. + */ + public void onFullyHidden() { + if (!mShowingSoon) { + cancelShowRunnable(); + inflateView(); + mFalsingManager.onBouncerHidden(); + } + } + private final Runnable mShowRunnable = new Runnable() { @Override public void run() { @@ -247,6 +283,18 @@ public class KeyguardBouncer { mBouncerPromptReason = mCallback.getBouncerPromptReason(); } + /** + * Current notification panel expansion + * @param fraction 0 when notification panel is collapsed and 1 when expanded. + * @see StatusBarKeyguardViewManager#onPanelExpansionChanged + */ + public void setExpansion(float fraction) { + if (mKeyguardView != null) { + mKeyguardView.setAlpha(MathUtils.map(ALPHA_EXPANSION_THRESHOLD, 1, 1, 0, fraction)); + mKeyguardView.setTranslationY(fraction * mKeyguardView.getHeight()); + } + } + protected void ensureView() { // Removal of the view might be deferred to reduce unlock latency, // in this case we need to force the removal, otherwise we'll diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java index 0cf26df7b3778..1bd5e33031893 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java @@ -79,14 +79,9 @@ public class KeyguardClockPositionAlgorithm { private int mMaxShadeBottom; /** - * Margin that we should respect within the available space. + * Minimum distance from the status bar. */ - private int mContainerPadding; - - /** - * Position where clock should be when the panel is collapsed. - */ - private int mClockYTarget; + private int mContainerTopPadding; /** * @see NotificationPanelView#getMaxPanelHeight() @@ -108,13 +103,23 @@ public class KeyguardClockPositionAlgorithm { */ private float mDarkAmount; + /** + * If keyguard will require a password or just fade away. + */ + private boolean mCurrentlySecure; + + /** + * If notification panel view currently has a touch. + */ + private boolean mTracking; + /** * Refreshes the dimension values. */ public void loadDimens(Resources res) { mClockNotificationsMargin = res.getDimensionPixelSize( R.dimen.keyguard_clock_notifications_margin); - mContainerPadding = res.getDimensionPixelSize( + mContainerTopPadding = res.getDimensionPixelSize( R.dimen.keyguard_clock_top_margin); mBurnInPreventionOffsetX = res.getDimensionPixelSize( R.dimen.burn_in_prevention_offset_x); @@ -124,8 +129,8 @@ public class KeyguardClockPositionAlgorithm { public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight, float expandedHeight, float maxPanelHeight, int parentHeight, int keyguardStatusHeight, - float dark) { - mMinTopMargin = minTopMargin; + float dark, boolean secure, boolean tracking) { + mMinTopMargin = minTopMargin + mContainerTopPadding; mMaxShadeBottom = maxShadeBottom; mNotificationStackHeight = notificationStackHeight; mExpandedHeight = expandedHeight; @@ -133,13 +138,8 @@ public class KeyguardClockPositionAlgorithm { mHeight = parentHeight; mKeyguardStatusHeight = keyguardStatusHeight; mDarkAmount = dark; - - // Where the clock should stop when swiping up. - // This should be outside of the display when unlocked or - // under then status bar when the bouncer will be shown - mClockYTarget = -mKeyguardStatusHeight; - // TODO: on bouncer animation follow-up CL - // mClockYTarget = mMinTopMargin + mContainerPadding; + mCurrentlySecure = secure; + mTracking = tracking; } public void run(Result result) { @@ -173,8 +173,8 @@ public class KeyguardClockPositionAlgorithm { float y = containerCenter - mKeyguardStatusHeight * CLOCK_HEIGHT_WEIGHT - mClockNotificationsMargin - mNotificationStackHeight / 2; - if (y < mMinTopMargin + mContainerPadding) { - y = mMinTopMargin + mContainerPadding; + if (y < mMinTopMargin) { + y = mMinTopMargin; } // Don't allow the clock base to be under half of the screen @@ -190,18 +190,32 @@ public class KeyguardClockPositionAlgorithm { // Dark: Align the bottom edge of the clock at about half of the screen: final float clockYDark = getMaxClockY() + burnInPreventionOffsetY(); float clockYRegular = getExpandedClockPosition(); + float clockYTarget = mCurrentlySecure ? mMinTopMargin : -mKeyguardStatusHeight; // Move clock up while collapsing the shade final float shadeExpansion = mExpandedHeight / mMaxPanelHeight; - final float clockY = MathUtils.lerp(mClockYTarget, clockYRegular, shadeExpansion); + final float clockY = MathUtils.lerp(clockYTarget, clockYRegular, shadeExpansion); return (int) MathUtils.lerp(clockY, clockYDark, mDarkAmount); } + /** + * We might want to fade out the clock when the user is swiping up. + * One exception is when the bouncer will become visible, in this cause the clock + * should always persist. + * + * @param y Current clock Y. + * @return Alpha from 0 to 1. + */ private float getClockAlpha(int y) { - float alphaKeyguard = Math.max(0, Math.min(1, (y - mMinTopMargin) - / Math.max(1f, getExpandedClockPosition() - mMinTopMargin))); - alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard); + float alphaKeyguard; + if (mCurrentlySecure) { + alphaKeyguard = 1; + } else { + alphaKeyguard = Math.max(0, Math.min(1, (y - mMinTopMargin) + / Math.max(1f, getExpandedClockPosition() - mMinTopMargin))); + alphaKeyguard = Interpolators.ACCELERATE.getInterpolation(alphaKeyguard); + } return MathUtils.lerp(alphaKeyguard, 1f, mDarkAmount); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java index 9d2480b22460f..2711d7ac7a89b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java @@ -238,7 +238,6 @@ public class NotificationPanelView extends PanelView implements private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger(); private boolean mNoVisibleNotifications = true; private ValueAnimator mDarkAnimator; - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private boolean mUserSetupComplete; private int mQsNotificationTopPadding; private float mExpandOffset; @@ -265,10 +264,8 @@ public class NotificationPanelView extends PanelView implements mKeyguardStatusBar = findViewById(R.id.keyguard_header); mKeyguardStatusView = findViewById(R.id.keyguard_status_view); - mNotificationContainerParent = (NotificationsQuickSettingsContainer) - findViewById(R.id.notification_container_parent); - mNotificationStackScroller = (NotificationStackScrollLayout) - findViewById(R.id.notification_stack_scroller); + mNotificationContainerParent = findViewById(R.id.notification_container_parent); + mNotificationStackScroller = findViewById(R.id.notification_stack_scroller); mNotificationStackScroller.setOnHeightChangedListener(this); mNotificationStackScroller.setOverscrollTopChangedListener(this); mNotificationStackScroller.setOnEmptySpaceClickListener(this); @@ -470,7 +467,9 @@ public class NotificationPanelView extends PanelView implements getMaxPanelHeight(), totalHeight, mKeyguardStatusView.getHeight(), - mDarkAmount); + mDarkAmount, + mStatusBar.isKeyguardCurrentlySecure(), + mTracking); mClockPositionAlgorithm.run(mClockPositionResult); if (animate || mClockAnimator != null) { startClockAnimation(mClockPositionResult.clockX, mClockPositionResult.clockY); @@ -1710,7 +1709,16 @@ public class NotificationPanelView extends PanelView implements } private void updateKeyguardBottomAreaAlpha() { - float alpha = Math.min(getKeyguardContentsAlpha(), 1 - getQsExpansionFraction()); + // There are two possible panel expansion behaviors: + // • User dragging up to unlock: we want to fade out as quick as possible + // (ALPHA_EXPANSION_THRESHOLD) to avoid seeing the bouncer over the bottom area. + // • User tapping on lock screen: bouncer won't be visible but panel expansion will + // change due to "unlock hint animation." In this case, fading out the bottom area + // would also hide the message that says "swipe to unlock," we don't want to do that. + float expansionAlpha = MathUtils.map(isUnlockHintRunning() + ? 0 : KeyguardBouncer.ALPHA_EXPANSION_THRESHOLD, 1f, + 0f, 1f, getExpandedFraction()); + float alpha = Math.min(expansionAlpha, 1 - getQsExpansionFraction()); mKeyguardBottomArea.setAlpha(alpha); mKeyguardBottomArea.setImportantForAccessibility(alpha == 0f ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS @@ -1809,7 +1817,7 @@ public class NotificationPanelView extends PanelView implements @Override protected void onTrackingStarted() { - mFalsingManager.onTrackingStarted(); + mFalsingManager.onTrackingStarted(mStatusBar.isKeyguardCurrentlySecure()); super.onTrackingStarted(); if (mQsFullyExpanded) { mQsExpandImmediate = true; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java index cefe97200ca93..b448967f6ac71 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java @@ -27,6 +27,7 @@ public abstract class PanelBar extends FrameLayout { public static final boolean DEBUG = false; public static final String TAG = PanelBar.class.getSimpleName(); private static final boolean SPEW = false; + private boolean mBouncerShowing; public static final void LOG(String fmt, Object... args) { if (!DEBUG) return; @@ -65,6 +66,7 @@ public abstract class PanelBar extends FrameLayout { } public void setBouncerShowing(boolean showing) { + mBouncerShowing = showing; int important = showing ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS : IMPORTANT_FOR_ACCESSIBILITY_AUTO; @@ -122,7 +124,7 @@ public abstract class PanelBar extends FrameLayout { boolean fullyOpened = false; if (SPEW) LOG("panelExpansionChanged: start state=%d", mState); PanelView pv = mPanel; - pv.setVisibility(expanded ? VISIBLE : INVISIBLE); + pv.setVisibility(expanded || mBouncerShowing ? VISIBLE : INVISIBLE); // adjust any other panels that may be partially visible if (expanded) { if (mState == STATE_CLOSED) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java index 7c91a40a7c4ae..3de0a41dc67db 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java @@ -23,14 +23,8 @@ import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; -import android.database.ContentObserver; -import android.os.AsyncTask; -import android.os.Handler; import android.os.SystemClock; -import android.os.UserHandle; import android.os.VibrationEffect; -import android.os.Vibrator; -import android.provider.Settings; import android.util.AttributeSet; import android.util.Log; import android.view.InputDevice; @@ -51,10 +45,10 @@ import com.android.systemui.doze.DozeLog; import com.android.systemui.statusbar.FlingAnimationUtils; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.VibratorHelper; -import com.android.systemui.statusbar.phone.HeadsUpManagerPhone; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.util.function.BiConsumer; public abstract class PanelView extends FrameLayout { public static final boolean DEBUG = PanelBar.DEBUG; @@ -69,6 +63,7 @@ public abstract class PanelView extends FrameLayout { private boolean mVibrateOnOpening; protected boolean mLaunchingNotification; private int mFixedDuration = NO_FIXED_DURATION; + private BiConsumer mExpansionListener; private final void logf(String fmt, Object... args) { Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args)); @@ -326,7 +321,8 @@ public abstract class PanelView extends FrameLayout { cancelPeek(); onTrackingStarted(); } - if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp()) { + if (isFullyCollapsed() && !mHeadsUpManager.hasPinnedHeadsUp() + && !mStatusBar.isBouncerShowing()) { startOpening(event); } break; @@ -490,7 +486,8 @@ public abstract class PanelView extends FrameLayout { if (mUpdateFlingOnLayout) { mUpdateFlingVelocity = vel; } - } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking) { + } else if (mPanelClosedOnDown && !mHeadsUpManager.hasPinnedHeadsUp() && !mTracking + && !mStatusBar.isBouncerShowing()) { long timePassed = SystemClock.uptimeMillis() - mDownTime; if (timePassed < ViewConfiguration.getLongPressTimeout()) { // Lets show the user that he can actually expand the panel @@ -499,7 +496,7 @@ public abstract class PanelView extends FrameLayout { // We need to collapse the panel since we peeked to the small height. postOnAnimation(mPostCollapseRunnable); } - } else { + } else if (!mStatusBar.isBouncerShowing()) { boolean expands = onEmptySpaceClick(mInitialTouchX); onTrackingStopped(expands); } @@ -1099,6 +1096,10 @@ public abstract class PanelView extends FrameLayout { mStatusBar.onUnlockHintStarted(); } + public boolean isUnlockHintRunning() { + return mHintAnimationRunning; + } + /** * Phase 1: Move everything upwards. */ @@ -1190,6 +1191,13 @@ public abstract class PanelView extends FrameLayout { mBar.panelExpansionChanged(mExpandedFraction, mExpandedFraction > 0f || mPeekAnimator != null || mInstantExpanding || isPanelVisibleBecauseOfHeadsUp() || mTracking || mHeightAnimator != null); + if (mExpansionListener != null) { + mExpansionListener.accept(mExpandedFraction, mTracking); + } + } + + public void setExpansionListener(BiConsumer consumer) { + mExpansionListener = consumer; } protected abstract boolean isPanelVisibleBecauseOfHeadsUp(); 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 e59a6b56d0399..71376a553cdf5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -35,7 +35,6 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; -import android.view.animation.PathInterpolator; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.colorextraction.ColorExtractor; @@ -97,14 +96,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, * The most common scrim, the one under the keyguard. */ protected static final float SCRIM_BEHIND_ALPHA_KEYGUARD = GRADIENT_SCRIM_ALPHA; - /** - * We fade out the bottom scrim when the bouncer is visible. - */ - protected static final float SCRIM_BEHIND_ALPHA_UNLOCKING = 0.2f; - /** - * Opacity of the scrim behind the bouncer (the one doing actual background protection.) - */ - protected static final float SCRIM_IN_FRONT_ALPHA_LOCKED = GRADIENT_SCRIM_ALPHA_BUSY; static final int TAG_KEY_ANIM = R.id.scrim; private static final int TAG_START_ALPHA = R.id.scrim_alpha_start; @@ -130,7 +121,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, protected float mScrimBehindAlpha; protected float mScrimBehindAlphaResValue; protected float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD; - protected float mScrimBehindAlphaUnlocking = SCRIM_BEHIND_ALPHA_UNLOCKING; // Assuming the shade is expanded during initialization private float mExpansionFraction = 1f; @@ -177,6 +167,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mScrimVisibleListener = scrimVisibleListener; mContext = scrimBehind.getContext(); mUnlockMethodCache = UnlockMethodCache.getInstance(mContext); + mDarkenWhileDragging = !mUnlockMethodCache.canSkipBouncer(); mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); mLightBarController = lightBarController; mScrimBehindAlphaResValue = mContext.getResources().getFloat(R.dimen.scrim_behind_alpha); @@ -300,10 +291,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, return mState; } - protected void setScrimBehindValues(float scrimBehindAlphaKeyguard, - float scrimBehindAlphaUnlocking) { + protected void setScrimBehindValues(float scrimBehindAlphaKeyguard) { mScrimBehindAlphaKeyguard = scrimBehindAlphaKeyguard; - mScrimBehindAlphaUnlocking = scrimBehindAlphaUnlocking; ScrimState[] states = ScrimState.values(); for (int i = 0; i < states.length; i++) { states[i].setScrimBehindAlphaKeyguard(scrimBehindAlphaKeyguard); @@ -404,9 +393,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, float interpolatedFract = getInterpolatedFraction(); float alphaBehind = mState.getBehindAlpha(mNotificationDensity); if (mDarkenWhileDragging) { - mCurrentBehindAlpha = MathUtils.lerp(mScrimBehindAlphaUnlocking, alphaBehind, + mCurrentBehindAlpha = MathUtils.lerp(GRADIENT_SCRIM_ALPHA_BUSY, alphaBehind, interpolatedFract); - mCurrentInFrontAlpha = (1f - interpolatedFract) * SCRIM_IN_FRONT_ALPHA_LOCKED; + mCurrentInFrontAlpha = 0; } else { mCurrentBehindAlpha = MathUtils.lerp(0 /* start */, alphaBehind, interpolatedFract); @@ -455,7 +444,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, if (mNeedsDrawableColorUpdate) { mNeedsDrawableColorUpdate = false; final GradientColors currentScrimColors; - if (mState == ScrimState.KEYGUARD || mState == ScrimState.BOUNCER) { + if (mState == ScrimState.KEYGUARD || mState == ScrimState.BOUNCER_OCCLUDED + || mState == ScrimState.BOUNCER) { // Always animate color changes if we're seeing the keyguard mScrimInFront.setColors(mLockColors, true /* animated */); mScrimBehind.setColors(mLockColors, true /* animated */); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java index 053c5a3b59667..58100efbcf81d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java @@ -66,20 +66,31 @@ public enum ScrimState { }, /** - * Showing password challenge. + * Showing password challenge on the keyguard. */ BOUNCER(1) { @Override public void prepare(ScrimState previousState) { - mCurrentBehindAlpha = ScrimController.SCRIM_BEHIND_ALPHA_UNLOCKING; - mCurrentInFrontAlpha = ScrimController.SCRIM_IN_FRONT_ALPHA_LOCKED; + mCurrentBehindAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; + mCurrentInFrontAlpha = 0f; + } + }, + + /** + * Showing password challenge on top of a FLAG_SHOW_WHEN_LOCKED activity. + */ + BOUNCER_OCCLUDED(2) { + @Override + public void prepare(ScrimState previousState) { + mCurrentBehindAlpha = 0; + mCurrentInFrontAlpha = ScrimController.GRADIENT_SCRIM_ALPHA_BUSY; } }, /** * Changing screen brightness from quick settings. */ - BRIGHTNESS_MIRROR(2) { + BRIGHTNESS_MIRROR(3) { @Override public void prepare(ScrimState previousState) { mCurrentBehindAlpha = 0; @@ -90,7 +101,7 @@ public enum ScrimState { /** * Always on display or screen off. */ - AOD(3) { + AOD(4) { @Override public void prepare(ScrimState previousState) { final boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn(); @@ -110,7 +121,7 @@ public enum ScrimState { /** * When phone wakes up because you received a notification. */ - PULSING(4) { + PULSING(5) { @Override public void prepare(ScrimState previousState) { mCurrentInFrontAlpha = 0; @@ -125,7 +136,7 @@ public enum ScrimState { /** * Unlocked on top of an app (launcher or any other activity.) */ - UNLOCKED(5) { + UNLOCKED(6) { @Override public void prepare(ScrimState previousState) { mCurrentBehindAlpha = 0; 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 899b93626a7f1..a305bfc7b0ab6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1296,7 +1296,7 @@ public class StatusBar extends SystemUI implements DemoMode, mDozeScrimController, keyguardViewMediator, mScrimController, this, UnlockMethodCache.getInstance(mContext)); mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this, - getBouncerContainer(), mFingerprintUnlockController); + getBouncerContainer(), mNotificationPanel, mFingerprintUnlockController); mKeyguardIndicationController .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); mFingerprintUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager); @@ -4619,7 +4619,8 @@ public class StatusBar extends SystemUI implements DemoMode, == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK; if (mBouncerShowing) { - mScrimController.transitionTo(ScrimState.BOUNCER); + mScrimController.transitionTo( + mIsOccluded ? ScrimState.BOUNCER_OCCLUDED : ScrimState.BOUNCER); } else if (mLaunchCameraOnScreenTurningOn || isInLaunchTransition()) { mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback); } else if (mBrightnessMirrorVisible) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index a009d80dad4f6..8d536d8ca45a5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -31,10 +31,10 @@ import android.view.ViewGroup; import android.view.ViewRootImpl; import android.view.WindowManagerGlobal; +import com.android.internal.util.LatencyTracker; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; -import com.android.internal.util.LatencyTracker; import com.android.keyguard.ViewMediatorCallback; import com.android.systemui.DejankUtils; import com.android.systemui.Dependency; @@ -75,6 +75,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb protected LockPatternUtils mLockPatternUtils; protected ViewMediatorCallback mViewMediatorCallback; protected StatusBar mStatusBar; + private NotificationPanelView mNotificationPanelView; private FingerprintUnlockController mFingerprintUnlockController; private ViewGroup mContainer; @@ -88,6 +89,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb protected boolean mFirstUpdate = true; protected boolean mLastShowing; protected boolean mLastOccluded; + private boolean mLastTracking; private boolean mLastBouncerShowing; private boolean mLastBouncerDismissible; protected boolean mLastRemoteInputActive; @@ -124,6 +126,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb public void registerStatusBar(StatusBar statusBar, ViewGroup container, + NotificationPanelView notificationPanelView, FingerprintUnlockController fingerprintUnlockController, DismissCallbackRegistry dismissCallbackRegistry) { mStatusBar = statusBar; @@ -131,6 +134,32 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mFingerprintUnlockController = fingerprintUnlockController; mBouncer = SystemUIFactory.getInstance().createKeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils, container, dismissCallbackRegistry); + mNotificationPanelView = notificationPanelView; + notificationPanelView.setExpansionListener(this::onPanelExpansionChanged); + } + + private void onPanelExpansionChanged(float expansion, boolean tracking) { + // We don't want to translate the bounce when the keyguard is occluded, because we're in + // a FLAG_SHOW_WHEN_LOCKED activity and need to conserve the original animation. + // We also don't want to show the bouncer when the user quickly taps on the display. + final boolean noLongerTracking = mLastTracking != tracking && !tracking; + if (mOccluded || mNotificationPanelView.isUnlockHintRunning()) { + mBouncer.setExpansion(0); + } else if (mShowing && mStatusBar.isKeyguardCurrentlySecure() && !mDozing) { + mBouncer.setExpansion(expansion); + if (expansion == 1) { + mBouncer.onFullyHidden(); + updateStates(); + } else if (!mBouncer.isShowing()) { + mBouncer.show(true /* resetSecuritySelection */, false /* notifyFalsing */); + } else if (noLongerTracking) { + // Notify that falsing manager should stop its session when user stops touching, + // even before the animation ends, to guarantee that we're not recording sensitive + // data. + mBouncer.onFullyShown(); + } + } + mLastTracking = tracking; } /** diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 3ed2fe14a0b60..bfa469eba99fa 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -170,12 +170,22 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test - public void transitionToBouncer() { + public void transitionToKeyguardBouncer() { mScrimController.transitionTo(ScrimState.BOUNCER); mScrimController.finishAnimationsImmediately(); // Front scrim should be transparent // Back scrim should be visible without tint - assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + assertScrimVisibility(VISIBILITY_FULLY_TRANSPARENT, VISIBILITY_SEMI_TRANSPARENT); + assertScrimTint(mScrimBehind, false /* tinted */); + } + + @Test + public void transitionToBouncer() { + mScrimController.transitionTo(ScrimState.BOUNCER_OCCLUDED); + mScrimController.finishAnimationsImmediately(); + // Front scrim should be transparent + // Back scrim should be visible without tint + assertScrimVisibility(VISIBILITY_SEMI_TRANSPARENT, VISIBILITY_FULLY_TRANSPARENT); assertScrimTint(mScrimBehind, false /* tinted */); }