Merge "Add alt auth affordance for keyguard notif-taps" into sc-dev

This commit is contained in:
Beverly Tai
2021-03-16 20:07:41 +00:00
committed by Android (Google) Code Review
19 changed files with 560 additions and 50 deletions

View File

@@ -0,0 +1,25 @@
<!-- Copyright (C) 2021 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid
android:color="?android:attr/colorBackground"/>
<size
android:width="64dp"
android:height="64dp"/>
</shape>

View File

@@ -20,7 +20,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- TODO: add background protection -->
<!-- Background protection -->
<ImageView
android:id="@+id/udfps_keyguard_fp_bg"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/fingerprint_bg"
android:visibility="gone"/>
<!-- Fingerprint -->
<ImageView

View File

@@ -79,6 +79,10 @@ abstract class UdfpsAnimationView extends FrameLayout {
return mPauseAuth ? mAlpha : 255;
}
boolean isPauseAuth() {
return mPauseAuth;
}
private int expansionToAlpha(float expansion) {
// Fade to 0 opacity when reaching this expansion amount
final float maxExpansion = 0.4f;

View File

@@ -24,10 +24,16 @@ import android.annotation.NonNull;
import android.graphics.PointF;
import android.graphics.RectF;
import com.android.systemui.Dumpable;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.ViewController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Handles:
* 1. registering for listeners when its view is attached and unregistering on view detached
@@ -39,33 +45,50 @@ import com.android.systemui.util.ViewController;
* - doze time event
*/
abstract class UdfpsAnimationViewController<T extends UdfpsAnimationView>
extends ViewController<T> {
extends ViewController<T> implements Dumpable {
@NonNull final StatusBarStateController mStatusBarStateController;
@NonNull final StatusBar mStatusBar;
@NonNull final DumpManager mDumpManger;
private boolean mNotificationShadeExpanded;
private int mStatusBarState;
protected UdfpsAnimationViewController(
T view,
StatusBarStateController statusBarStateController,
StatusBar statusBar) {
@NonNull StatusBarStateController statusBarStateController,
@NonNull StatusBar statusBar,
@NonNull DumpManager dumpManager) {
super(view);
mStatusBarStateController = statusBarStateController;
mStatusBar = statusBar;
mDumpManger = dumpManager;
}
abstract @NonNull String getTag();
@Override
protected void onViewAttached() {
mStatusBarStateController.addCallback(mStateListener);
mStateListener.onStateChanged(mStatusBarStateController.getState());
mStatusBar.addExpansionChangedListener(mStatusBarExpansionChangedListener);
mDumpManger.registerDumpable(getTag(), this);
}
@Override
protected void onViewDetached() {
mStatusBarStateController.removeCallback(mStateListener);
mStatusBar.removeExpansionChangedListener(mStatusBarExpansionChangedListener);
mDumpManger.unregisterDumpable(getTag());
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("mStatusBarState=" + StatusBarState.toShortString(mStatusBarState));
pw.println("mNotificationShadeExpanded=" + mNotificationShadeExpanded);
pw.println("shouldPauseAuth()=" + shouldPauseAuth());
pw.println("isPauseAuth=" + mView.isPauseAuth());
}
/**

View File

@@ -16,6 +16,9 @@
package com.android.systemui.biometrics;
import android.annotation.NonNull;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -24,9 +27,15 @@ import com.android.systemui.statusbar.phone.StatusBar;
*/
class UdfpsBpViewController extends UdfpsAnimationViewController<UdfpsBpView> {
protected UdfpsBpViewController(
UdfpsBpView view,
StatusBarStateController statusBarStateController,
StatusBar statusBar) {
super(view, statusBarStateController, statusBar);
@NonNull UdfpsBpView view,
@NonNull StatusBarStateController statusBarStateController,
@NonNull StatusBar statusBar,
@NonNull DumpManager dumpManager) {
super(view, statusBarStateController, statusBar, dumpManager);
}
@Override
@NonNull String getTag() {
return "UdfpsBpViewController";
}
}

View File

@@ -50,8 +50,10 @@ import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.concurrency.DelayableExecutor;
import javax.inject.Inject;
@@ -83,6 +85,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
private final DelayableExecutor mFgExecutor;
@NonNull private final StatusBar mStatusBar;
@NonNull private final StatusBarStateController mStatusBarStateController;
@NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
@NonNull private final DumpManager mDumpManager;
// Currently the UdfpsController supports a single UDFPS sensor. If devices have multiple
// sensors, this, in addition to a lot of the code here, will be updated.
@VisibleForTesting final FingerprintSensorPropertiesInternal mSensorProps;
@@ -299,7 +303,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
WindowManager windowManager,
@NonNull StatusBarStateController statusBarStateController,
@Main DelayableExecutor fgExecutor,
@NonNull StatusBar statusBar) {
@NonNull StatusBar statusBar,
@NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
@NonNull DumpManager dumpManager) {
mContext = context;
mInflater = inflater;
// The fingerprint manager is queried for UDFPS before this class is constructed, so the
@@ -309,6 +315,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
mFgExecutor = fgExecutor;
mStatusBar = statusBar;
mStatusBarStateController = statusBarStateController;
mKeyguardViewManager = statusBarKeyguardViewManager;
mDumpManager = dumpManager;
mSensorProps = findFirstUdfps();
// At least one UDFPS sensor exists
@@ -457,7 +465,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
enrollView,
mServerRequest.mEnrollHelper,
mStatusBarStateController,
mStatusBar
mStatusBar,
mDumpManager
);
case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD:
UdfpsKeyguardView keyguardView = (UdfpsKeyguardView)
@@ -466,7 +475,9 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
return new UdfpsKeyguardViewController(
keyguardView,
mStatusBarStateController,
mStatusBar
mStatusBar,
mKeyguardViewManager,
mDumpManager
);
case IUdfpsOverlayController.REASON_AUTH_BP:
// note: empty controller, currently shows no visual affordance
@@ -475,7 +486,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
return new UdfpsBpViewController(
bpView,
mStatusBarStateController,
mStatusBar
mStatusBar,
mDumpManager
);
case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER:
UdfpsFpmOtherView authOtherView = (UdfpsFpmOtherView)
@@ -484,7 +496,8 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
return new UdfpsFpmOtherViewController(
authOtherView,
mStatusBarStateController,
mStatusBar
mStatusBar,
mDumpManager
);
default:
Log.d(TAG, "Animation for reason " + reason + " not supported yet");

View File

@@ -61,12 +61,14 @@ public abstract class UdfpsDrawable extends Drawable {
*/
protected void updateFingerprintIconBounds(@NonNull Rect bounds) {
mFingerprintDrawable.setBounds(bounds);
invalidateSelf();
}
@Override
public void setAlpha(int alpha) {
mAlpha = alpha;
mFingerprintDrawable.setAlpha(mAlpha);
invalidateSelf();
}
boolean isIlluminationShowing() {
@@ -74,7 +76,11 @@ public abstract class UdfpsDrawable extends Drawable {
}
void setIlluminationShowing(boolean showing) {
if (mIlluminationShowing == showing) {
return;
}
mIlluminationShowing = showing;
invalidateSelf();
}
@Override

View File

@@ -21,6 +21,7 @@ import android.graphics.PointF;
import android.view.View;
import com.android.systemui.R;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -32,16 +33,22 @@ public class UdfpsEnrollViewController extends UdfpsAnimationViewController<Udfp
@NonNull private final UdfpsEnrollHelper mEnrollHelper;
protected UdfpsEnrollViewController(
UdfpsEnrollView view,
@NonNull UdfpsEnrollView view,
@NonNull UdfpsEnrollHelper enrollHelper,
StatusBarStateController statusBarStateController,
StatusBar statusBar) {
super(view, statusBarStateController, statusBar);
@NonNull StatusBarStateController statusBarStateController,
@NonNull StatusBar statusBar,
@NonNull DumpManager dumpManager) {
super(view, statusBarStateController, statusBar, dumpManager);
mEnrollHelper = enrollHelper;
mProgressBar = mView.findViewById(R.id.progress_bar);
mView.setEnrollHelper(mEnrollHelper);
}
@Override
@NonNull String getTag() {
return "UdfpsEnrollViewController";
}
@Override
protected void onViewAttached() {
super.onViewAttached();

View File

@@ -16,6 +16,9 @@
package com.android.systemui.biometrics;
import android.annotation.NonNull;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
@@ -27,9 +30,15 @@ import com.android.systemui.statusbar.phone.StatusBar;
*/
class UdfpsFpmOtherViewController extends UdfpsAnimationViewController<UdfpsFpmOtherView> {
protected UdfpsFpmOtherViewController(
UdfpsFpmOtherView view,
StatusBarStateController statusBarStateController,
StatusBar statusBar) {
super(view, statusBarStateController, statusBar);
@NonNull UdfpsFpmOtherView view,
@NonNull StatusBarStateController statusBarStateController,
@NonNull StatusBar statusBar,
@NonNull DumpManager dumpManager) {
super(view, statusBarStateController, statusBar, dumpManager);
}
@Override
@NonNull String getTag() {
return "UdfpsFpmOtherViewController";
}
}

View File

@@ -36,14 +36,14 @@ import com.android.systemui.doze.DozeReceiver;
public class UdfpsKeyguardDrawable extends UdfpsDrawable implements DozeReceiver {
private static final String TAG = "UdfpsAnimationKeyguard";
private final int mLockScreenColor;
private final int mAmbientDisplayColor;
@NonNull private final Context mContext;
private final int mMaxBurnInOffsetX;
private final int mMaxBurnInOffsetY;
private int mLockScreenColor;
// AOD anti-burn-in offsets
private final int mMaxBurnInOffsetX;
private final int mMaxBurnInOffsetY;
private float mInterpolatedDarkAmount;
private float mBurnInOffsetX;
private float mBurnInOffsetY;
@@ -95,4 +95,10 @@ public class UdfpsKeyguardDrawable extends UdfpsDrawable implements DozeReceiver
mInterpolatedDarkAmount = eased;
updateAodPositionAndColor();
}
void setLockScreenColor(int color) {
if (mLockScreenColor == color) return;
mLockScreenColor = color;
updateAodPositionAndColor();
}
}

View File

@@ -16,13 +16,23 @@
package com.android.systemui.biometrics;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import androidx.annotation.Nullable;
import com.android.settingslib.Utils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.statusbar.StatusBarState;
/**
* View corresponding with udfps_keyguard_view.xml
@@ -30,6 +40,14 @@ import com.android.systemui.R;
public class UdfpsKeyguardView extends UdfpsAnimationView {
private final UdfpsKeyguardDrawable mFingerprintDrawable;
private ImageView mFingerprintView;
private int mWallpaperTexColor;
private int mStatusBarState;
// used when highlighting fp icon:
private int mTextColorPrimary;
private ImageView mBgProtection;
private AnimatorSet mAnimatorSet;
public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
@@ -38,8 +56,15 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mFingerprintView = findViewById(R.id.udfps_keyguard_animation_fp_view);
mFingerprintView.setImageDrawable(mFingerprintDrawable);
mFingerprintView.setForeground(mFingerprintDrawable);
mBgProtection = findViewById(R.id.udfps_keyguard_fp_bg);
mWallpaperTexColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
mTextColorPrimary = Utils.getColorAttrDefaultColor(mContext,
android.R.attr.textColorPrimary);
}
@Override
@@ -54,7 +79,114 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
return true;
}
void setStatusBarState(int statusBarState) {
mStatusBarState = statusBarState;
if (!isShadeLocked()) {
mFingerprintView.setAlpha(1f);
mFingerprintDrawable.setLockScreenColor(mWallpaperTexColor);
}
}
void onDozeAmountChanged(float linear, float eased) {
mFingerprintDrawable.onDozeAmountChanged(linear, eased);
invalidate();
}
/**
* Animates in the bg protection circle behind the fp icon to highlight the icon.
*/
void animateHighlightFp() {
if (mBgProtection.getVisibility() == View.VISIBLE && mBgProtection.getAlpha() == 1f) {
// already fully highlighted, don't re-animate
return;
}
if (mAnimatorSet != null) {
mAnimatorSet.cancel();
}
ValueAnimator fpIconAnim;
if (isShadeLocked()) {
// set color and fade in since we weren't showing before
mFingerprintDrawable.setLockScreenColor(mTextColorPrimary);
fpIconAnim = ObjectAnimator.ofFloat(mFingerprintView, View.ALPHA, 0f, 1f);
} else {
// update icon color
fpIconAnim = new ValueAnimator();
fpIconAnim.setIntValues(mWallpaperTexColor, mTextColorPrimary);
fpIconAnim.setEvaluator(new ArgbEvaluator());
fpIconAnim.addUpdateListener(valueAnimator -> mFingerprintDrawable.setLockScreenColor(
(Integer) valueAnimator.getAnimatedValue()));
}
mAnimatorSet = new AnimatorSet();
mAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mAnimatorSet.setDuration(500);
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mBgProtection.setVisibility(View.VISIBLE);
}
});
mAnimatorSet.playTogether(
ObjectAnimator.ofFloat(mBgProtection, View.ALPHA, 0f, 1f),
ObjectAnimator.ofFloat(mBgProtection, View.SCALE_X, 0f, 1f),
ObjectAnimator.ofFloat(mBgProtection, View.SCALE_Y, 0f, 1f),
fpIconAnim);
mAnimatorSet.start();
}
private boolean isShadeLocked() {
return mStatusBarState == StatusBarState.SHADE_LOCKED;
}
/**
* Animates out the bg protection circle behind the fp icon to unhighlight the icon.
*/
void animateUnhighlightFp(@Nullable Runnable onEndAnimation) {
if (mBgProtection.getVisibility() == View.GONE) {
// already hidden
return;
}
if (mAnimatorSet != null) {
mAnimatorSet.cancel();
}
ValueAnimator fpIconAnim;
if (isShadeLocked()) {
// fade out
fpIconAnim = ObjectAnimator.ofFloat(mFingerprintView, View.ALPHA, 1f, 0f);
} else {
// update icon color
fpIconAnim = new ValueAnimator();
fpIconAnim.setIntValues(mTextColorPrimary, mWallpaperTexColor);
fpIconAnim.setEvaluator(new ArgbEvaluator());
fpIconAnim.addUpdateListener(valueAnimator -> mFingerprintDrawable.setLockScreenColor(
(Integer) valueAnimator.getAnimatedValue()));
}
mAnimatorSet = new AnimatorSet();
mAnimatorSet.playTogether(
ObjectAnimator.ofFloat(mBgProtection, View.ALPHA, 1f, 0f),
ObjectAnimator.ofFloat(mBgProtection, View.SCALE_X, 1f, 0f),
ObjectAnimator.ofFloat(mBgProtection, View.SCALE_Y, 1f, 0f),
fpIconAnim);
mAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
mAnimatorSet.setDuration(500);
mAnimatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mBgProtection.setVisibility(View.GONE);
if (onEndAnimation != null) {
onEndAnimation.run();
}
}
});
mAnimatorSet.start();
}
boolean isAnimating() {
return mAnimatorSet != null && mAnimatorSet.isRunning();
}
}

View File

@@ -16,34 +16,62 @@
package com.android.systemui.biometrics;
import android.annotation.NonNull;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import java.io.FileDescriptor;
import java.io.PrintWriter;
/**
* Class that coordinates non-HBM animations during keyguard authentication.
*/
public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<UdfpsKeyguardView> {
@NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
private boolean mForceShow;
protected UdfpsKeyguardViewController(
UdfpsKeyguardView view,
StatusBarStateController statusBarStateController,
StatusBar statusBar) {
super(view, statusBarStateController, statusBar);
@NonNull UdfpsKeyguardView view,
@NonNull StatusBarStateController statusBarStateController,
@NonNull StatusBar statusBar,
@NonNull StatusBarKeyguardViewManager statusBarKeyguardViewManager,
@NonNull DumpManager dumpManager) {
super(view, statusBarStateController, statusBar, dumpManager);
mKeyguardViewManager = statusBarKeyguardViewManager;
}
@Override
@NonNull String getTag() {
return "UdfpsKeyguardViewController";
}
@Override
protected void onViewAttached() {
super.onViewAttached();
mStatusBarStateController.addCallback(mStateListener);
final float dozeAmount = mStatusBarStateController.getDozeAmount();
mStatusBarStateController.addCallback(mStateListener);
mStateListener.onDozeAmountChanged(dozeAmount, dozeAmount);
mStateListener.onStateChanged(mStatusBarStateController.getState());
mKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
}
@Override
protected void onViewDetached() {
super.onViewDetached();
mStatusBarStateController.removeCallback(mStateListener);
mAlternateAuthInterceptor.reset();
mKeyguardViewManager.setAlternateAuthInterceptor(null);
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
super.dump(fd, pw, args);
pw.println("mForceShow=" + mForceShow);
}
/**
@@ -56,7 +84,11 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
mForceShow = forceShow;
updatePauseAuth();
// TODO: animate show/hide background protection
if (mForceShow) {
mView.animateHighlightFp();
} else {
mView.animateUnhighlightFp(() -> mKeyguardViewManager.cancelPostAuthActions());
}
}
/**
@@ -76,6 +108,50 @@ public class UdfpsKeyguardViewController extends UdfpsAnimationViewController<Ud
@Override
public void onDozeAmountChanged(float linear, float eased) {
mView.onDozeAmountChanged(linear, eased);
if (linear != 0) forceShow(false);
}
@Override
public void onStateChanged(int statusBarState) {
mView.setStatusBarState(statusBarState);
}
};
private final StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor =
new StatusBarKeyguardViewManager.AlternateAuthInterceptor() {
@Override
public boolean showAlternativeAuthMethod() {
if (mForceShow) {
return false;
}
forceShow(true);
return true;
}
@Override
public boolean reset() {
if (!mForceShow) {
return false;
}
forceShow(false);
return true;
}
@Override
public boolean isShowingAlternativeAuth() {
return mForceShow;
}
@Override
public boolean isAnimating() {
return mView.isAnimating();
}
@Override
public void dump(PrintWriter pw) {
pw.print(getTag());
}
};
}

View File

@@ -3386,6 +3386,9 @@ public class NotificationPanelViewController extends PanelViewController {
return new TouchHandler() {
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mStatusBarKeyguardViewManager.isShowingAlternativeAuthOrAnimating()) {
return true;
}
if (mBlockTouches || mQsFullyExpanded && mQs.disallowPanelTouches()) {
return false;
}
@@ -3413,6 +3416,12 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public boolean onTouch(View v, MotionEvent event) {
final boolean showingOrAnimatingAltAuth =
mStatusBarKeyguardViewManager.isShowingAlternativeAuthOrAnimating();
if (showingOrAnimatingAltAuth) {
mStatusBarKeyguardViewManager.resetAlternateAuth();
}
if (mBlockTouches || (mQsFullyExpanded && mQs != null
&& mQs.disallowPanelTouches())) {
return false;
@@ -3464,7 +3473,7 @@ public class NotificationPanelViewController extends PanelViewController {
handled = true;
}
handled |= super.onTouch(v, event);
return !mDozing || mPulsing || handled;
return !mDozing || mPulsing || handled || showingOrAnimatingAltAuth;
}
};
}

View File

@@ -453,7 +453,8 @@ public abstract class PanelViewController {
// We need to collapse the panel since we peeked to the small height.
mView.postOnAnimation(mPostCollapseRunnable);
}
} else if (!mStatusBar.isBouncerShowing()) {
} else if (!mStatusBar.isBouncerShowing()
&& !mStatusBarKeyguardViewManager.isShowingAlternativeAuthOrAnimating()) {
boolean expands = onEmptySpaceClick(mInitialTouchX);
onTrackingStopped(expands);
}

View File

@@ -88,6 +88,17 @@ public enum ScrimState {
}
},
AUTH_SCRIMMED {
@Override
public void prepare(ScrimState previousState) {
mFrontTint = Color.BLACK;
mBehindAlpha = 0f;
mFrontAlpha = .66f;
mBubbleAlpha = 0f;
}
},
/**
* Showing password challenge on the keyguard.
*/

View File

@@ -4147,7 +4147,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
@VisibleForTesting
void updateScrimController() {
public void updateScrimController() {
Trace.beginSection("StatusBar#updateScrimController");
// We don't want to end up in KEYGUARD state when we're unlocking with
@@ -4163,7 +4163,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
if (mBouncerShowing) {
if (mStatusBarKeyguardViewManager.isShowingAlternativeAuth()) {
mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
} else if (mBouncerShowing) {
// Bouncer needs the front scrim when it's on top of an activity,
// tapping on a notification, editing QS or being dismissed by
// FLAG_DISMISS_KEYGUARD_ACTIVITY.

View File

@@ -38,6 +38,7 @@ import android.view.ViewRootImpl;
import android.view.WindowManagerGlobal;
import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
@@ -199,6 +200,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private final DockManager mDockManager;
private final KeyguardUpdateMonitor mKeyguardUpdateManager;
private KeyguardBypassController mBypassController;
@Nullable private AlternateAuthInterceptor mAlternateAuthInterceptor;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@@ -271,6 +273,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
registerListeners();
}
public void setAlternateAuthInterceptor(@Nullable AlternateAuthInterceptor authInterceptor) {
mAlternateAuthInterceptor = authInterceptor;
}
private void registerListeners() {
mKeyguardUpdateManager.registerCallback(mUpdateMonitorCallback);
mStatusBarStateController.addCallback(this);
@@ -434,11 +440,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
if (mShowing) {
// If we were showing the bouncer and then aborting, we need to also clear out any
// potential actions unless we actually unlocked.
mAfterKeyguardGoneAction = null;
if (mKeyguardGoneCancelAction != null) {
mKeyguardGoneCancelAction.run();
mKeyguardGoneCancelAction = null;
}
cancelPostAuthActions();
}
mBouncer.hide(destroyView);
cancelPendingWakeupAction();
@@ -474,6 +476,14 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return;
}
if (mAlternateAuthInterceptor != null
&& mAlternateAuthInterceptor.showAlternativeAuthMethod()) {
mStatusBar.updateScrimController();
mAfterKeyguardGoneAction = r;
mKeyguardGoneCancelAction = cancelAction;
return;
}
if (!afterKeyguardGone) {
mBouncer.showWithDismissAction(r, cancelAction);
} else {
@@ -508,11 +518,21 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
} else {
showBouncerOrKeyguard(hideBouncerWhenShowing);
}
resetAlternateAuth();
mKeyguardUpdateManager.sendKeyguardReset();
updateStates();
}
}
/**
* Stop showing any alternate auth methods
*/
public void resetAlternateAuth() {
if (mAlternateAuthInterceptor != null && mAlternateAuthInterceptor.reset()) {
mStatusBar.updateScrimController();
}
}
@Override
public void onStartedWakingUp() {
mStatusBar.getNotificationShadeWindowView().getWindowInsetsController()
@@ -834,6 +854,20 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return mBouncer.isFullscreenBouncer();
}
/**
* Clear out any potential actions that were saved to run when the device is unlocked
*/
public void cancelPostAuthActions() {
if (bouncerIsOrWillBeShowing()) {
return; // allow bouncer to trigger saved actions
}
mAfterKeyguardGoneAction = null;
if (mKeyguardGoneCancelAction != null) {
mKeyguardGoneCancelAction.run();
mKeyguardGoneCancelAction = null;
}
}
private long getNavBarShowDelay() {
if (mKeyguardStateController.isKeyguardFadingAway()) {
return mKeyguardStateController.getKeyguardFadingAwayDelay();
@@ -1063,6 +1097,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
if (mBouncer != null) {
mBouncer.dump(pw);
}
if (mAlternateAuthInterceptor != null) {
pw.println("AltAuthInterceptor: ");
mAlternateAuthInterceptor.dump(pw);
}
}
@Override
@@ -1079,6 +1118,17 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
return mBouncer;
}
public boolean isShowingAlternativeAuth() {
return mAlternateAuthInterceptor != null
&& mAlternateAuthInterceptor.isShowingAlternativeAuth();
}
public boolean isShowingAlternativeAuthOrAnimating() {
return mAlternateAuthInterceptor != null
&& (mAlternateAuthInterceptor.isShowingAlternativeAuth()
|| mAlternateAuthInterceptor.isAnimating());
}
private static class DismissWithActionRequest {
final OnDismissAction dismissAction;
final Runnable cancelAction;
@@ -1093,4 +1143,36 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
this.message = message;
}
}
/**
* Delegate used to send show/reset events to an alternate authentication method instead of the
* bouncer.
*/
public interface AlternateAuthInterceptor {
/**
* @return whether alternative auth method was newly shown
*/
boolean showAlternativeAuthMethod();
/**
* reset the state to the default (only keyguard showing, no auth methods showing)
* @return whether alternative auth method was newly hidden
*/
boolean reset();
/**
* @return true if alternative auth method is showing
*/
boolean isShowingAlternativeAuth();
/**
* print information for the alternate auth interceptor registered
*/
void dump(PrintWriter pw);
/**
* @return true if the new auth method is currently animating in or out.
*/
boolean isAnimating();
}
}

View File

@@ -44,8 +44,10 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.util.concurrency.FakeExecutor;
import com.android.systemui.util.time.FakeSystemClock;
@@ -91,6 +93,10 @@ public class UdfpsControllerTest extends SysuiTestCase {
@Mock
private StatusBar mStatusBar;
@Mock
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
private DumpManager mDumpManager;
@Mock
private IUdfpsOverlayControllerCallback mUdfpsOverlayControllerCallback;
private FakeExecutor mFgExecutor;
@@ -129,7 +135,9 @@ public class UdfpsControllerTest extends SysuiTestCase {
mWindowManager,
mStatusBarStateController,
mFgExecutor,
mStatusBar);
mStatusBar,
mStatusBarKeyguardViewManager,
mDumpManager);
verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
mOverlayController = mOverlayCaptor.getValue();

View File

@@ -16,6 +16,8 @@
package com.android.systemui.biometrics;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -26,9 +28,11 @@ import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import org.junit.Before;
import org.junit.Test;
@@ -51,24 +55,34 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
private StatusBarStateController mStatusBarStateController;
@Mock
private StatusBar mStatusBar;
@Mock
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Mock
private DumpManager mDumpManager;
private UdfpsKeyguardViewController mController;
// Capture listeners so that they can be used to send events
@Captor private ArgumentCaptor<StatusBarStateController.StateListener> mStateListenerCaptor;
private StatusBarStateController.StateListener mParentListener;
private StatusBarStateController.StateListener mDozeListener;
private StatusBarStateController.StateListener mParentStatusBarStateListener;
private StatusBarStateController.StateListener mStatusBarStateListener;
@Captor private ArgumentCaptor<StatusBar.ExpansionChangedListener> mExpansionListenerCaptor;
private StatusBar.ExpansionChangedListener mExpansionListener;
@Captor private ArgumentCaptor<StatusBarKeyguardViewManager.AlternateAuthInterceptor>
mAltAuthInterceptorCaptor;
private StatusBarKeyguardViewManager.AlternateAuthInterceptor mAltAuthInterceptor;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mController = new UdfpsKeyguardViewController(
mView,
mStatusBarStateController,
mStatusBar);
mStatusBar,
mStatusBarKeyguardViewManager,
mDumpManager);
}
@Test
@@ -86,7 +100,7 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
@Test
public void testViewControllerQueriesSBStateOnAttached() {
mController.onViewAttached();
verify(mStatusBarStateController).getState();
verify(mStatusBarStateController, times(2)).getState();
verify(mStatusBarStateController).getDozeAmount();
final float dozeAmount = .88f;
@@ -106,8 +120,8 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
captureExpansionListener();
mController.onViewDetached();
verify(mStatusBarStateController).removeCallback(mParentListener);
verify(mStatusBarStateController).removeCallback(mDozeListener);
verify(mStatusBarStateController).removeCallback(mParentStatusBarStateListener);
verify(mStatusBarStateController).removeCallback(mStatusBarStateListener);
verify(mStatusBar).removeExpansionChangedListener(mExpansionListener);
}
@@ -118,21 +132,88 @@ public class UdfpsKeyguardViewControllerTest extends SysuiTestCase {
final float linear = .55f;
final float eased = .65f;
mDozeListener.onDozeAmountChanged(linear, eased);
mStatusBarStateListener.onDozeAmountChanged(linear, eased);
verify(mView).onDozeAmountChanged(linear, eased);
}
@Test
public void testShouldNotPauseAuthOnKeyguard() {
mController.onViewAttached();
captureStatusBarStateListeners();
captureExpansionListener();
sendStatusBarStateChanged(StatusBarState.KEYGUARD);
assertFalse(mController.shouldPauseAuth());
}
@Test
public void testShouldPauseAuthOnShadeLocked() {
mController.onViewAttached();
captureStatusBarStateListeners();
captureExpansionListener();
sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED);
assertTrue(mController.shouldPauseAuth());
}
@Test
public void testOverrideShouldPauseAuthOnShadeLocked() {
mController.onViewAttached();
captureStatusBarStateListeners();
captureAltAuthInterceptor();
sendStatusBarStateChanged(StatusBarState.SHADE_LOCKED);
assertTrue(mController.shouldPauseAuth());
mAltAuthInterceptor.showAlternativeAuthMethod(); // force show
assertFalse(mController.shouldPauseAuth());
assertTrue(mAltAuthInterceptor.isShowingAlternativeAuth());
mAltAuthInterceptor.reset(); // stop force show
assertTrue(mController.shouldPauseAuth());
assertFalse(mAltAuthInterceptor.isShowingAlternativeAuth());
}
@Test
public void testOnDetachedStateReset() {
// GIVEN view is attached, alt auth is force being shown
mController.onViewAttached();
captureStatusBarStateListeners();
captureAltAuthInterceptor();
mAltAuthInterceptor.showAlternativeAuthMethod(); // alt auth force show
// WHEN view is detached
mController.onViewDetached();
// THEN alt auth state reports not showing
assertFalse(mAltAuthInterceptor.isShowingAlternativeAuth());
}
private void sendStatusBarStateChanged(int statusBarState) {
mStatusBarStateListener.onStateChanged(statusBarState);
mParentStatusBarStateListener.onStateChanged(statusBarState);
}
private void captureStatusBarStateListeners() {
verify(mStatusBarStateController, times(2)).addCallback(mStateListenerCaptor.capture());
List<StatusBarStateController.StateListener> stateListeners =
mStateListenerCaptor.getAllValues();
mParentListener = stateListeners.get(0);
mDozeListener = stateListeners.get(1);
mParentStatusBarStateListener = stateListeners.get(0);
mStatusBarStateListener = stateListeners.get(1);
}
private void captureExpansionListener() {
verify(mStatusBar).addExpansionChangedListener(mExpansionListenerCaptor.capture());
mExpansionListener = mExpansionListenerCaptor.getValue();
}
private void captureAltAuthInterceptor() {
verify(mStatusBarKeyguardViewManager).setAlternateAuthInterceptor(
mAltAuthInterceptorCaptor.capture());
mAltAuthInterceptor = mAltAuthInterceptorCaptor.getValue();
}
}