Update co-ex error logic
KeyguardIndication (bottom text area on LS) - show transient messages for a minimum of 2000ms not including animation time - if dual auth is enrolled: only show face auth errors if the user explicitly requested face auth In general, don't request face auth on the global actions menu (likely left over from when the power menu had affordances for components requiring authentication) Test: atest SystemUITest Fixes: 186302245 Bug: 183698582 Change-Id: I0290c66addc9981bf3fe20de24110e2d35e1f8eb
This commit is contained in:
@@ -173,7 +173,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
@Override
|
||||
public void onSwipeUp() {
|
||||
if (!mUpdateMonitor.isFaceDetectionRunning()) {
|
||||
mUpdateMonitor.requestFaceAuth();
|
||||
mUpdateMonitor.requestFaceAuth(true);
|
||||
mKeyguardSecurityCallback.userActivity();
|
||||
showMessage(null, null);
|
||||
}
|
||||
|
||||
@@ -309,6 +309,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
private RingerModeTracker mRingerModeTracker;
|
||||
private int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
|
||||
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
|
||||
private boolean mIsFaceAuthUserRequested;
|
||||
private LockPatternUtils mLockPatternUtils;
|
||||
private final IDreamManager mDreamManager;
|
||||
private boolean mIsDreaming;
|
||||
@@ -2057,12 +2058,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
/**
|
||||
* Requests face authentication if we're on a state where it's allowed.
|
||||
* This will re-trigger auth in case it fails.
|
||||
* @param userInitiatedRequest true if the user explicitly requested face auth
|
||||
*/
|
||||
public void requestFaceAuth() {
|
||||
if (DEBUG) Log.d(TAG, "requestFaceAuth()");
|
||||
public void requestFaceAuth(boolean userInitiatedRequest) {
|
||||
if (DEBUG) Log.d(TAG, "requestFaceAuth() userInitiated=" + userInitiatedRequest);
|
||||
mIsFaceAuthUserRequested |= userInitiatedRequest;
|
||||
updateFaceListeningState();
|
||||
}
|
||||
|
||||
public boolean isFaceAuthUserRequested() {
|
||||
return mIsFaceAuthUserRequested;
|
||||
}
|
||||
|
||||
/**
|
||||
* In case face auth is running, cancel it.
|
||||
*/
|
||||
@@ -2079,6 +2086,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|
||||
mHandler.removeCallbacks(mRetryFaceAuthentication);
|
||||
boolean shouldListenForFace = shouldListenForFace();
|
||||
if (mFaceRunningState == BIOMETRIC_STATE_RUNNING && !shouldListenForFace) {
|
||||
mIsFaceAuthUserRequested = false;
|
||||
stopListeningForFace();
|
||||
} else if (mFaceRunningState != BIOMETRIC_STATE_RUNNING && shouldListenForFace) {
|
||||
startListeningForFace();
|
||||
|
||||
@@ -30,7 +30,6 @@ import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.keyguard.KeyguardUpdateMonitor;
|
||||
import com.android.settingslib.Utils;
|
||||
import com.android.systemui.plugins.GlobalActions;
|
||||
import com.android.systemui.scrim.ScrimDrawable;
|
||||
@@ -51,7 +50,6 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
|
||||
private final KeyguardStateController mKeyguardStateController;
|
||||
private final DeviceProvisionedController mDeviceProvisionedController;
|
||||
private final BlurUtils mBlurUtils;
|
||||
private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
|
||||
private final CommandQueue mCommandQueue;
|
||||
private GlobalActionsDialogLite mGlobalActionsDialog;
|
||||
private boolean mDisabled;
|
||||
@@ -60,15 +58,13 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
|
||||
public GlobalActionsImpl(Context context, CommandQueue commandQueue,
|
||||
Lazy<GlobalActionsDialogLite> globalActionsDialogLazy, BlurUtils blurUtils,
|
||||
KeyguardStateController keyguardStateController,
|
||||
DeviceProvisionedController deviceProvisionedController,
|
||||
KeyguardUpdateMonitor keyguardUpdateMonitor) {
|
||||
DeviceProvisionedController deviceProvisionedController) {
|
||||
mContext = context;
|
||||
mGlobalActionsDialogLazy = globalActionsDialogLazy;
|
||||
mKeyguardStateController = keyguardStateController;
|
||||
mDeviceProvisionedController = deviceProvisionedController;
|
||||
mCommandQueue = commandQueue;
|
||||
mBlurUtils = blurUtils;
|
||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||
mCommandQueue.addCallback(this);
|
||||
}
|
||||
|
||||
@@ -87,7 +83,6 @@ public class GlobalActionsImpl implements GlobalActions, CommandQueue.Callbacks
|
||||
mGlobalActionsDialog = mGlobalActionsDialogLazy.get();
|
||||
mGlobalActionsDialog.showOrHideDialog(mKeyguardStateController.isShowing(),
|
||||
mDeviceProvisionedController.isDeviceProvisioned());
|
||||
mKeyguardUpdateMonitor.requestFaceAuth();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,18 +40,22 @@ public class KeyguardIndication {
|
||||
private final View.OnClickListener mOnClickListener;
|
||||
@Nullable
|
||||
private final Drawable mBackground;
|
||||
@Nullable
|
||||
private final Long mMinVisibilityMillis; // in milliseconds
|
||||
|
||||
private KeyguardIndication(
|
||||
CharSequence message,
|
||||
ColorStateList textColor,
|
||||
Drawable icon,
|
||||
View.OnClickListener onClickListener,
|
||||
Drawable background) {
|
||||
Drawable background,
|
||||
Long minVisibilityMillis) {
|
||||
mMessage = message;
|
||||
mTextColor = textColor;
|
||||
mIcon = icon;
|
||||
mOnClickListener = onClickListener;
|
||||
mBackground = background;
|
||||
mMinVisibilityMillis = minVisibilityMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,6 +93,14 @@ public class KeyguardIndication {
|
||||
return mBackground;
|
||||
}
|
||||
|
||||
/**
|
||||
* Minimum time to show text in milliseconds.
|
||||
* @return null if unspecified
|
||||
*/
|
||||
public @Nullable Long getMinVisibilityMillis() {
|
||||
return mMinVisibilityMillis;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String str = "KeyguardIndication{";
|
||||
@@ -96,6 +108,7 @@ public class KeyguardIndication {
|
||||
if (mIcon != null) str += " mIcon=" + mIcon;
|
||||
if (mOnClickListener != null) str += " mOnClickListener=" + mOnClickListener;
|
||||
if (mBackground != null) str += " mBackground=" + mBackground;
|
||||
if (mMinVisibilityMillis != null) str += " mMinVisibilityMillis=" + mMinVisibilityMillis;
|
||||
str += "}";
|
||||
return str;
|
||||
}
|
||||
@@ -109,6 +122,7 @@ public class KeyguardIndication {
|
||||
private View.OnClickListener mOnClickListener;
|
||||
private ColorStateList mTextColor;
|
||||
private Drawable mBackground;
|
||||
private Long mMinVisibilityMillis;
|
||||
|
||||
public Builder() { }
|
||||
|
||||
@@ -154,6 +168,15 @@ public class KeyguardIndication {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optional. Set a required minimum visibility time in milliseconds for the text
|
||||
* to show.
|
||||
*/
|
||||
public Builder setMinVisibilityMillis(Long minVisibilityMillis) {
|
||||
this.mMinVisibilityMillis = minVisibilityMillis;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the KeyguardIndication.
|
||||
*/
|
||||
@@ -166,7 +189,8 @@ public class KeyguardIndication {
|
||||
}
|
||||
|
||||
return new KeyguardIndication(
|
||||
mMessage, mTextColor, mIcon, mOnClickListener, mBackground);
|
||||
mMessage, mTextColor, mIcon, mOnClickListener, mBackground,
|
||||
mMinVisibilityMillis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,12 +167,14 @@ public class KeyguardIndicationRotateTextViewController extends
|
||||
* - can be presented with an "error" color if isError is true
|
||||
*/
|
||||
public void showTransient(CharSequence newIndication, boolean isError) {
|
||||
final long inAnimationDuration = 600L; // see KeyguardIndicationTextView.getYInDuration
|
||||
updateIndication(INDICATION_TYPE_TRANSIENT,
|
||||
new KeyguardIndication.Builder()
|
||||
.setMessage(newIndication)
|
||||
.setTextColor(isError
|
||||
? Utils.getColorError(getContext())
|
||||
: mInitialTextColorState)
|
||||
.setMinVisibilityMillis(2000L + inAnimationDuration)
|
||||
.build(),
|
||||
/* showImmediately */true);
|
||||
}
|
||||
|
||||
@@ -885,6 +885,11 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
|
||||
.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (biometricSourceType == BiometricSourceType.FACE && shouldSuppressFaceMsg()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean showSwipeToUnlock =
|
||||
msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
|
||||
if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
|
||||
@@ -912,7 +917,8 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
|
||||
// The face timeout message is not very actionable, let's ask the user to
|
||||
// manually retry.
|
||||
if (!mStatusBarKeyguardViewManager.isBouncerShowing()
|
||||
&& mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
|
||||
&& mKeyguardUpdateMonitor.isUdfpsEnrolled()
|
||||
&& mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
|
||||
// suggest trying fingerprint
|
||||
showTransientIndication(R.string.keyguard_try_fingerprint);
|
||||
} else {
|
||||
@@ -952,7 +958,18 @@ public class KeyguardIndicationController implements KeyguardStateController.Cal
|
||||
|| msgId == FingerprintManager.FINGERPRINT_ERROR_USER_CANCELED);
|
||||
}
|
||||
|
||||
private boolean shouldSuppressFaceMsg() {
|
||||
// For dual biometric, don't show face auth messages unless face auth was explicitly
|
||||
// requested by the user.
|
||||
return mKeyguardUpdateMonitor.isUdfpsEnrolled()
|
||||
&& mKeyguardUpdateMonitor.isFingerprintDetectionRunning()
|
||||
&& !mKeyguardUpdateMonitor.isFaceAuthUserRequested();
|
||||
}
|
||||
|
||||
private boolean shouldSuppressFaceError(int msgId, KeyguardUpdateMonitor updateMonitor) {
|
||||
if (shouldSuppressFaceMsg()) {
|
||||
return true;
|
||||
}
|
||||
// Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
|
||||
// as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
|
||||
// pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
|
||||
|
||||
@@ -38,7 +38,7 @@ import java.util.LinkedList;
|
||||
* A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open").
|
||||
*/
|
||||
public class KeyguardIndicationTextView extends TextView {
|
||||
private static final long MSG_DURATION_MILLIS = 1500;
|
||||
private static final long MSG_MIN_DURATION_MILLIS_DEFAULT = 1500;
|
||||
private long mNextAnimationTime = 0;
|
||||
private boolean mAnimationsEnabled = true;
|
||||
private LinkedList<CharSequence> mMessages = new LinkedList<>();
|
||||
@@ -104,8 +104,13 @@ public class KeyguardIndicationTextView extends TextView {
|
||||
long delay = Math.max(0, mNextAnimationTime - timeInMillis);
|
||||
setNextAnimationTime(timeInMillis + delay + getFadeOutDuration());
|
||||
|
||||
final long minDurationMillis =
|
||||
(indication != null && indication.getMinVisibilityMillis() != null)
|
||||
? indication.getMinVisibilityMillis()
|
||||
: MSG_MIN_DURATION_MILLIS_DEFAULT;
|
||||
|
||||
if (!text.equals("") || hasIcon) {
|
||||
setNextAnimationTime(mNextAnimationTime + MSG_DURATION_MILLIS);
|
||||
setNextAnimationTime(mNextAnimationTime + minDurationMillis);
|
||||
animSetBuilder.before(getInAnimator());
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class KeyguardLiftController constructor(
|
||||
// Not listening anymore since trigger events unregister themselves
|
||||
isListening = false
|
||||
updateListeningState()
|
||||
keyguardUpdateMonitor.requestFaceAuth()
|
||||
keyguardUpdateMonitor.requestFaceAuth(true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2038,7 +2038,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
// When expanding QS, let's authenticate the user if possible,
|
||||
// this will speed up notification actions.
|
||||
if (height == 0) {
|
||||
mStatusBar.requestFaceAuth();
|
||||
mStatusBar.requestFaceAuth(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3176,7 +3176,7 @@ public class NotificationPanelViewController extends PanelViewController {
|
||||
case KEYGUARD:
|
||||
if (!mDozingOnDown) {
|
||||
if (mKeyguardBypassController.getBypassEnabled()) {
|
||||
mUpdateMonitor.requestFaceAuth();
|
||||
mUpdateMonitor.requestFaceAuth(true);
|
||||
} else {
|
||||
mLockscreenGestureLogger.write(MetricsEvent.ACTION_LS_HINT,
|
||||
0 /* lengthDp - N/A */, 0 /* velocityDp - N/A */);
|
||||
|
||||
@@ -1723,9 +1723,9 @@ public class StatusBar extends SystemUI implements DemoMode,
|
||||
/**
|
||||
* Asks {@link KeyguardUpdateMonitor} to run face auth.
|
||||
*/
|
||||
public void requestFaceAuth() {
|
||||
public void requestFaceAuth(boolean userInitiatedRequest) {
|
||||
if (!mKeyguardStateController.canDismissLockScreen()) {
|
||||
mKeyguardUpdateMonitor.requestFaceAuth();
|
||||
mKeyguardUpdateMonitor.requestFaceAuth(userInitiatedRequest);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -569,7 +569,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
|
||||
// Stop scanning when bouncer becomes visible
|
||||
setKeyguardBouncerVisibility(true);
|
||||
clearInvocations(mFaceManager);
|
||||
mKeyguardUpdateMonitor.requestFaceAuth();
|
||||
mKeyguardUpdateMonitor.requestFaceAuth(true);
|
||||
verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user