Loading packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml +1 −2 Original line number Diff line number Diff line Loading @@ -19,8 +19,7 @@ android:layout_height="match_parent" android:background="@android:color/transparent" android:clipChildren="false" android:clipToPadding="false" android:fitsSystemWindows="true"> android:clipToPadding="false"> <include style="@style/BouncerSecurityContainer" Loading packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +7 −0 Original line number Diff line number Diff line Loading @@ -231,6 +231,13 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit public void showUsabilityHint() { } @Override public boolean disallowInterceptTouch(MotionEvent event) { mTempRect.set(mLockPatternView.getLeft(), mLockPatternView.getTop(), mLockPatternView.getRight(), mLockPatternView.getBottom()); return mTempRect.contains((int) event.getX(), (int) event.getY()); } /** TODO: hook this up */ public void cleanUp() { if (DEBUG) Log.v(TAG, "Cleanup() called on " + this); Loading packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +138 −2 Original line number Diff line number Diff line Loading @@ -26,12 +26,18 @@ import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.util.StatsLog; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.FrameLayout; import androidx.annotation.VisibleForTesting; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; Loading Loading @@ -60,6 +66,11 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe // Bouncer is dismissed due to sim card unlock code entered. private static final int BOUNCER_DISMISS_SIM = 4; // Make the view move slower than the finger, as if the spring were applying force. private static final float TOUCH_Y_MULTIPLIER = 0.25f; // How much you need to drag the bouncer to trigger an auth retry (in dps.) private static final float MIN_DRAG_SIZE = 10; private KeyguardSecurityModel mSecurityModel; private LockPatternUtils mLockPatternUtils; Loading @@ -70,10 +81,18 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe private SecurityCallback mSecurityCallback; private AlertDialog mAlertDialog; private InjectionInflationController mInjectionInflationController; private boolean mSwipeUpToRetry; private final ViewConfiguration mViewConfiguration; private final SpringAnimation mSpringAnimation; private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private final KeyguardUpdateMonitor mUpdateMonitor; private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); private float mLastTouchY = -1; private int mActivePointerId = -1; private boolean mIsDragging; private float mStartTouchY = -1; // Used to notify the container when something interesting happens. public interface SecurityCallback { Loading Loading @@ -104,9 +123,10 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mSecurityModel = new KeyguardSecurityModel(context); mLockPatternUtils = new LockPatternUtils(context); mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y); mInjectionInflationController = new InjectionInflationController( SystemUIFactory.getInstance().getRootComponent()); mViewConfiguration = ViewConfiguration.get(context); } public void setSecurityCallback(SecurityCallback callback) { Loading @@ -118,6 +138,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe if (mCurrentSecuritySelection != SecurityMode.None) { getSecurityView(mCurrentSecuritySelection).onResume(reason); } updateBiometricRetry(); updatePaddings(); } @Override Loading @@ -131,6 +153,95 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } } @Override public boolean shouldDelayChildPressedState() { return true; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: int pointerIndex = event.getActionIndex(); mStartTouchY = event.getY(pointerIndex); mActivePointerId = event.getPointerId(pointerIndex); mVelocityTracker.clear(); break; case MotionEvent.ACTION_MOVE: if (mIsDragging) { return true; } if (!mSwipeUpToRetry) { return false; } // Avoid dragging the pattern view if (mCurrentSecurityView.disallowInterceptTouch(event)) { return false; } int index = event.findPointerIndex(mActivePointerId); int touchSlop = mViewConfiguration.getScaledTouchSlop(); if (mCurrentSecurityView != null && mStartTouchY - event.getY(index) > touchSlop) { mIsDragging = true; return true; } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mIsDragging = false; break; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { final int action = event.getActionMasked(); switch (action) { case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); int pointerIndex = event.findPointerIndex(mActivePointerId); float y = event.getY(pointerIndex); if (mLastTouchY != -1) { float dy = y - mLastTouchY; setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER); } mLastTouchY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mActivePointerId = -1; mLastTouchY = -1; mIsDragging = false; startSpringAnimation(mVelocityTracker.getYVelocity()); break; case MotionEvent.ACTION_POINTER_UP: int index = event.getActionIndex(); int pointerId = event.getPointerId(index); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = index == 0 ? 1 : 0; mLastTouchY = event.getY(newPointerIndex); mActivePointerId = event.getPointerId(newPointerIndex); } break; } if (action == MotionEvent.ACTION_UP) { if (-getTranslationY() > TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, MIN_DRAG_SIZE, getResources().getDisplayMetrics())) { mUpdateMonitor.requestFaceAuth(); } } return true; } private void startSpringAnimation(float startVelocity) { mSpringAnimation .setStartVelocity(startVelocity) .animateToFinalPosition(0); } public void startAppearAnimation() { if (mCurrentSecuritySelection != SecurityMode.None) { getSecurityView(mCurrentSecuritySelection).startAppearAnimation(); Loading @@ -145,6 +256,18 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe return false; } /** * Enables/disables swipe up to retry on the bouncer. */ private void updateBiometricRetry() { SecurityMode securityMode = getSecurityMode(); int userId = KeyguardUpdateMonitor.getCurrentUser(); mSwipeUpToRetry = mUpdateMonitor.isUnlockWithFacePossible(userId) && securityMode != SecurityMode.SimPin && securityMode != SecurityMode.SimPuk && securityMode != SecurityMode.None; } public CharSequence getTitle() { return mSecurityViewFlipper.getTitle(); } Loading Loading @@ -195,6 +318,20 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); updatePaddings(); } private void updatePaddings() { int bottomPadding = getRootWindowInsets().getSystemWindowInsets().bottom; if (getPaddingBottom() == bottomPadding) { return; } setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottomPadding); } private void showDialog(String title, String message) { if (mAlertDialog != null) { mAlertDialog.dismiss(); Loading Loading @@ -467,7 +604,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext); if (success) { StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED, StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS); Loading packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java +11 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.keyguard; import android.content.res.ColorStateList; import android.view.MotionEvent; import com.android.internal.widget.LockPatternUtils; Loading Loading @@ -137,4 +138,14 @@ public interface KeyguardSecurityView { * @return The View's title. */ CharSequence getTitle(); /** * If the parent should not be allowed to intercept touch events. * @param event A touch event. * @return {@code true} if touch should be passed forward. * @see android.view.ViewGroup#requestDisallowInterceptTouchEvent(boolean) */ default boolean disallowInterceptTouch(MotionEvent event) { return false; } } packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +15 −5 Original line number Diff line number Diff line Loading @@ -1686,7 +1686,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { && mFpm.getEnrolledFingerprints(userId).size() > 0; } private boolean isUnlockWithFacePossible(int userId) { /** * If face hardware is available and user has enrolled. Not considering encryption or * lockdown state. */ public boolean isUnlockWithFacePossible(int userId) { return mFaceManager != null && mFaceManager.isHardwareDetected() && !isFaceDisabled(userId) && mFaceManager.hasEnrolledTemplates(userId); Loading Loading @@ -2273,6 +2277,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return isSimPinSecure(); } /** * If any SIM cards are currently secure. * @see #isSimPinSecure(State) */ public boolean isSimPinSecure() { // True if any SIM is pin secure for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) { Loading Loading @@ -2338,11 +2346,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return changed; } /** * If the {@code state} is currently requiring a SIM PIN, PUK, or is disabled. */ public static boolean isSimPinSecure(IccCardConstants.State state) { final IccCardConstants.State simState = state; return (simState == IccCardConstants.State.PIN_REQUIRED || simState == IccCardConstants.State.PUK_REQUIRED || simState == IccCardConstants.State.PERM_DISABLED); return (state == IccCardConstants.State.PIN_REQUIRED || state == IccCardConstants.State.PUK_REQUIRED || state == IccCardConstants.State.PERM_DISABLED); } public DisplayClientState getCachedDisplayClientState() { Loading Loading
packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml +1 −2 Original line number Diff line number Diff line Loading @@ -19,8 +19,7 @@ android:layout_height="match_parent" android:background="@android:color/transparent" android:clipChildren="false" android:clipToPadding="false" android:fitsSystemWindows="true"> android:clipToPadding="false"> <include style="@style/BouncerSecurityContainer" Loading
packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +7 −0 Original line number Diff line number Diff line Loading @@ -231,6 +231,13 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit public void showUsabilityHint() { } @Override public boolean disallowInterceptTouch(MotionEvent event) { mTempRect.set(mLockPatternView.getLeft(), mLockPatternView.getTop(), mLockPatternView.getRight(), mLockPatternView.getBottom()); return mTempRect.contains((int) event.getX(), (int) event.getY()); } /** TODO: hook this up */ public void cleanUp() { if (DEBUG) Log.v(TAG, "Cleanup() called on " + this); Loading
packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +138 −2 Original line number Diff line number Diff line Loading @@ -26,12 +26,18 @@ import android.util.AttributeSet; import android.util.Log; import android.util.Slog; import android.util.StatsLog; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.WindowManager; import android.widget.FrameLayout; import androidx.annotation.VisibleForTesting; import androidx.dynamicanimation.animation.DynamicAnimation; import androidx.dynamicanimation.animation.SpringAnimation; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; Loading Loading @@ -60,6 +66,11 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe // Bouncer is dismissed due to sim card unlock code entered. private static final int BOUNCER_DISMISS_SIM = 4; // Make the view move slower than the finger, as if the spring were applying force. private static final float TOUCH_Y_MULTIPLIER = 0.25f; // How much you need to drag the bouncer to trigger an auth retry (in dps.) private static final float MIN_DRAG_SIZE = 10; private KeyguardSecurityModel mSecurityModel; private LockPatternUtils mLockPatternUtils; Loading @@ -70,10 +81,18 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe private SecurityCallback mSecurityCallback; private AlertDialog mAlertDialog; private InjectionInflationController mInjectionInflationController; private boolean mSwipeUpToRetry; private final ViewConfiguration mViewConfiguration; private final SpringAnimation mSpringAnimation; private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); private final KeyguardUpdateMonitor mUpdateMonitor; private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class); private float mLastTouchY = -1; private int mActivePointerId = -1; private boolean mIsDragging; private float mStartTouchY = -1; // Used to notify the container when something interesting happens. public interface SecurityCallback { Loading Loading @@ -104,9 +123,10 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mSecurityModel = new KeyguardSecurityModel(context); mLockPatternUtils = new LockPatternUtils(context); mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext); mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y); mInjectionInflationController = new InjectionInflationController( SystemUIFactory.getInstance().getRootComponent()); mViewConfiguration = ViewConfiguration.get(context); } public void setSecurityCallback(SecurityCallback callback) { Loading @@ -118,6 +138,8 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe if (mCurrentSecuritySelection != SecurityMode.None) { getSecurityView(mCurrentSecuritySelection).onResume(reason); } updateBiometricRetry(); updatePaddings(); } @Override Loading @@ -131,6 +153,95 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } } @Override public boolean shouldDelayChildPressedState() { return true; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: int pointerIndex = event.getActionIndex(); mStartTouchY = event.getY(pointerIndex); mActivePointerId = event.getPointerId(pointerIndex); mVelocityTracker.clear(); break; case MotionEvent.ACTION_MOVE: if (mIsDragging) { return true; } if (!mSwipeUpToRetry) { return false; } // Avoid dragging the pattern view if (mCurrentSecurityView.disallowInterceptTouch(event)) { return false; } int index = event.findPointerIndex(mActivePointerId); int touchSlop = mViewConfiguration.getScaledTouchSlop(); if (mCurrentSecurityView != null && mStartTouchY - event.getY(index) > touchSlop) { mIsDragging = true; return true; } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: mIsDragging = false; break; } return false; } @Override public boolean onTouchEvent(MotionEvent event) { final int action = event.getActionMasked(); switch (action) { case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); int pointerIndex = event.findPointerIndex(mActivePointerId); float y = event.getY(pointerIndex); if (mLastTouchY != -1) { float dy = y - mLastTouchY; setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER); } mLastTouchY = y; break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mActivePointerId = -1; mLastTouchY = -1; mIsDragging = false; startSpringAnimation(mVelocityTracker.getYVelocity()); break; case MotionEvent.ACTION_POINTER_UP: int index = event.getActionIndex(); int pointerId = event.getPointerId(index); if (pointerId == mActivePointerId) { // This was our active pointer going up. Choose a new // active pointer and adjust accordingly. final int newPointerIndex = index == 0 ? 1 : 0; mLastTouchY = event.getY(newPointerIndex); mActivePointerId = event.getPointerId(newPointerIndex); } break; } if (action == MotionEvent.ACTION_UP) { if (-getTranslationY() > TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, MIN_DRAG_SIZE, getResources().getDisplayMetrics())) { mUpdateMonitor.requestFaceAuth(); } } return true; } private void startSpringAnimation(float startVelocity) { mSpringAnimation .setStartVelocity(startVelocity) .animateToFinalPosition(0); } public void startAppearAnimation() { if (mCurrentSecuritySelection != SecurityMode.None) { getSecurityView(mCurrentSecuritySelection).startAppearAnimation(); Loading @@ -145,6 +256,18 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe return false; } /** * Enables/disables swipe up to retry on the bouncer. */ private void updateBiometricRetry() { SecurityMode securityMode = getSecurityMode(); int userId = KeyguardUpdateMonitor.getCurrentUser(); mSwipeUpToRetry = mUpdateMonitor.isUnlockWithFacePossible(userId) && securityMode != SecurityMode.SimPin && securityMode != SecurityMode.SimPuk && securityMode != SecurityMode.None; } public CharSequence getTitle() { return mSecurityViewFlipper.getTitle(); } Loading Loading @@ -195,6 +318,20 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe mSecurityViewFlipper.setLockPatternUtils(mLockPatternUtils); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); updatePaddings(); } private void updatePaddings() { int bottomPadding = getRootWindowInsets().getSystemWindowInsets().bottom; if (getPaddingBottom() == bottomPadding) { return; } setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottomPadding); } private void showDialog(String title, String message) { if (mAlertDialog != null) { mAlertDialog.dismiss(); Loading Loading @@ -467,7 +604,6 @@ public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSe } public void reportUnlockAttempt(int userId, boolean success, int timeoutMs) { KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(mContext); if (success) { StatsLog.write(StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED, StatsLog.KEYGUARD_BOUNCER_PASSWORD_ENTERED__RESULT__SUCCESS); Loading
packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java +11 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.keyguard; import android.content.res.ColorStateList; import android.view.MotionEvent; import com.android.internal.widget.LockPatternUtils; Loading Loading @@ -137,4 +138,14 @@ public interface KeyguardSecurityView { * @return The View's title. */ CharSequence getTitle(); /** * If the parent should not be allowed to intercept touch events. * @param event A touch event. * @return {@code true} if touch should be passed forward. * @see android.view.ViewGroup#requestDisallowInterceptTouchEvent(boolean) */ default boolean disallowInterceptTouch(MotionEvent event) { return false; } }
packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +15 −5 Original line number Diff line number Diff line Loading @@ -1686,7 +1686,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { && mFpm.getEnrolledFingerprints(userId).size() > 0; } private boolean isUnlockWithFacePossible(int userId) { /** * If face hardware is available and user has enrolled. Not considering encryption or * lockdown state. */ public boolean isUnlockWithFacePossible(int userId) { return mFaceManager != null && mFaceManager.isHardwareDetected() && !isFaceDisabled(userId) && mFaceManager.hasEnrolledTemplates(userId); Loading Loading @@ -2273,6 +2277,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return isSimPinSecure(); } /** * If any SIM cards are currently secure. * @see #isSimPinSecure(State) */ public boolean isSimPinSecure() { // True if any SIM is pin secure for (SubscriptionInfo info : getSubscriptionInfo(false /* forceReload */)) { Loading Loading @@ -2338,11 +2346,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { return changed; } /** * If the {@code state} is currently requiring a SIM PIN, PUK, or is disabled. */ public static boolean isSimPinSecure(IccCardConstants.State state) { final IccCardConstants.State simState = state; return (simState == IccCardConstants.State.PIN_REQUIRED || simState == IccCardConstants.State.PUK_REQUIRED || simState == IccCardConstants.State.PERM_DISABLED); return (state == IccCardConstants.State.PIN_REQUIRED || state == IccCardConstants.State.PUK_REQUIRED || state == IccCardConstants.State.PERM_DISABLED); } public DisplayClientState getCachedDisplayClientState() { Loading