Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ca180d6 authored by Beverly's avatar Beverly Committed by Android Build Coastguard Worker
Browse files

Show UDFPS icon on AOD even if fp auth isn't running

* shows udfps if it's enrolled on AOD even if:
   * device requires strong auth (ie: after reboot, lockdown)
   * device is unlocked via smart lock

On click of the udfps icon in the above cases:
  * If the device is locked, the bouncer will show.
  * If the device is unlocked, the user will enter the device.

Fixes: 198315404
Test: manual
Change-Id: Id766df8f77427ae1db672507716bd38dc3462452
Merged-In: Id766df8f77427ae1db672507716bd38dc3462452
(cherry picked from commit c06bb2d2)
parent 3985ceb1
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -70,6 +70,19 @@
            android:padding="@dimen/lock_icon_padding"
            android:layout_gravity="center"
            android:scaleType="centerCrop"/>

        <!-- Fingerprint -->
        <!-- AOD dashed fingerprint icon with moving dashes -->
        <com.airbnb.lottie.LottieAnimationView
            android:id="@+id/lock_udfps_aod_fp"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="@dimen/lock_icon_padding"
            android:layout_gravity="center"
            android:scaleType="centerCrop"
            systemui:lottie_autoPlay="false"
            systemui:lottie_loop="true"
            systemui:lottie_rawRes="@raw/udfps_aod_fp"/>
    </com.android.keyguard.LockIconView>

    <com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer
+12 −7
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ public class LockIconView extends FrameLayout implements Dumpable {
    private int mRadius;

    private ImageView mLockIcon;
    private ImageView mUnlockBgView;
    private ImageView mBgView;

    private int mLockIconColor;

@@ -57,19 +57,19 @@ public class LockIconView extends FrameLayout implements Dumpable {
    public void onFinishInflate() {
        super.onFinishInflate();
        mLockIcon = findViewById(R.id.lock_icon);
        mUnlockBgView = findViewById(R.id.lock_icon_bg);
        mBgView = findViewById(R.id.lock_icon_bg);
    }

    void updateColorAndBackgroundVisibility(boolean useBackground) {
        if (useBackground) {
        if (useBackground && mLockIcon.getDrawable() != null) {
            mLockIconColor = Utils.getColorAttrDefaultColor(getContext(),
                    android.R.attr.textColorPrimary);
            mUnlockBgView.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg));
            mUnlockBgView.setVisibility(View.VISIBLE);
            mBgView.setBackground(getContext().getDrawable(R.drawable.fingerprint_bg));
            mBgView.setVisibility(View.VISIBLE);
        } else {
            mLockIconColor = Utils.getColorAttrDefaultColor(getContext(),
                    R.attr.wallpaperTextColorAccent);
            mUnlockBgView.setVisibility(View.GONE);
            mBgView.setVisibility(View.GONE);
        }

        mLockIcon.setImageTintList(ColorStateList.valueOf(mLockIconColor));
@@ -77,9 +77,14 @@ public class LockIconView extends FrameLayout implements Dumpable {

    void setImageDrawable(Drawable drawable) {
        mLockIcon.setImageDrawable(drawable);
        if (drawable == null) {
            mBgView.setVisibility(View.INVISIBLE);
        } else {
            mBgView.setVisibility(View.VISIBLE);
        }
    }

    void setCenterLocation(@NonNull PointF center, int radius) {
    public void setCenterLocation(@NonNull PointF center, int radius) {
        mLockIconCenter = center;
        mRadius = radius;

+102 −11
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.keyguard;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;

import static com.android.systemui.classifier.Classifier.LOCK_ICON;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInProgressOffset;

import android.content.Context;
import android.content.res.Configuration;
@@ -32,6 +34,7 @@ import android.media.AudioAttributes;
import android.os.Process;
import android.os.Vibrator;
import android.util.DisplayMetrics;
import android.util.MathUtils;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
@@ -58,6 +61,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.concurrency.DelayableExecutor;

import com.airbnb.lottie.LottieAnimationView;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Objects;
@@ -92,6 +97,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
    @NonNull private final DelayableExecutor mExecutor;
    private boolean mUdfpsEnrolled;

    @NonNull private LottieAnimationView mAodFp;

    @NonNull private final AnimatedVectorDrawable mFpToUnlockIcon;
    @NonNull private final AnimatedVectorDrawable mLockToUnlockIcon;
    @NonNull private final Drawable mLockIcon;
@@ -109,6 +116,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
    private boolean mIsKeyguardShowing;
    private boolean mUserUnlockedWithBiometric;
    private Runnable mCancelDelayedUpdateVisibilityRunnable;
    private Runnable mOnGestureDetectedRunnable;

    private boolean mUdfpsSupported;
    private float mHeightPixels;
@@ -118,6 +126,12 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
    private boolean mShowUnlockIcon;
    private boolean mShowLockIcon;

    // for udfps when strong auth is required or unlocked on AOD
    private boolean mShowAODFpIcon;
    private final int mMaxBurnInOffsetX;
    private final int mMaxBurnInOffsetY;
    private float mInterpolatedDarkAmount;

    private boolean mDownDetected;
    private boolean mDetectedLongPress;
    private final Rect mSensorTouchLocation = new Rect();
@@ -150,6 +164,12 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
        mVibrator = vibrator;

        final Context context = view.getContext();
        mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp);
        mMaxBurnInOffsetX = context.getResources()
                .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
        mMaxBurnInOffsetY = context.getResources()
                .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);

        mUnlockIcon = mView.getContext().getResources().getDrawable(
            R.drawable.ic_unlock,
            mView.getContext().getTheme());
@@ -173,15 +193,14 @@ public class LockIconViewController extends ViewController<LockIconView> impleme

    @Override
    protected void onViewAttached() {
        // we check this here instead of onInit since the FingerprintManager + FaceManager may not
        // have started up yet onInit
        mUdfpsSupported = mAuthController.getUdfpsSensorLocation() != null;

        updateIsUdfpsEnrolled();
        updateConfiguration();
        updateKeyguardShowing();
        mUserUnlockedWithBiometric = false;

        mIsBouncerShowing = mKeyguardViewController.isBouncerShowing();
        mIsDozing = mStatusBarStateController.isDozing();
        mInterpolatedDarkAmount = mStatusBarStateController.getDozeAmount();
        mRunningFPS = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
        mCanDismissLockScreen = mKeyguardStateController.canDismissLockScreen();
        mStatusBarState = mStatusBarStateController.getState();
@@ -189,15 +208,18 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
        updateColors();
        mConfigurationController.addCallback(mConfigurationListener);

        mAuthController.addCallback(mAuthControllerCallback);
        mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
        mStatusBarStateController.addCallback(mStatusBarStateListener);
        mKeyguardStateController.addCallback(mKeyguardStateCallback);
        mDownDetected = false;
        updateBurnInOffsets();
        updateVisibility();
    }

    @Override
    protected void onViewDetached() {
        mAuthController.removeCallback(mAuthControllerCallback);
        mConfigurationController.removeCallback(mConfigurationListener);
        mKeyguardUpdateMonitor.removeCallback(mKeyguardUpdateMonitorCallback);
        mStatusBarStateController.removeCallback(mStatusBarStateListener);
@@ -227,7 +249,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
            mCancelDelayedUpdateVisibilityRunnable = null;
        }

        if (!mIsKeyguardShowing) {
        if (!mIsKeyguardShowing && !mIsDozing) {
            mView.setVisibility(View.INVISIBLE);
            return;
        }
@@ -238,6 +260,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
        mShowLockIcon = !mCanDismissLockScreen && !mUserUnlockedWithBiometric && isLockScreen()
            && (!mUdfpsEnrolled || !mRunningFPS);
        mShowUnlockIcon = mCanDismissLockScreen && isLockScreen();
        mShowAODFpIcon = mIsDozing && mUdfpsEnrolled && !mRunningFPS;

        final CharSequence prevContentDescription = mView.getContentDescription();
        if (mShowLockIcon) {
@@ -260,10 +283,22 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
            }
            mView.setVisibility(View.VISIBLE);
            mView.setContentDescription(mUnlockedLabel);
        } else if (mShowAODFpIcon) {
            mView.setImageDrawable(null);
            mView.setContentDescription(null);
            mAodFp.setVisibility(View.VISIBLE);
            mAodFp.setContentDescription(mCanDismissLockScreen ? mUnlockedLabel : mLockedLabel);
            mView.setVisibility(View.VISIBLE);
        } else {
            mView.setVisibility(View.INVISIBLE);
            mView.setContentDescription(null);
        }

        if (!mShowAODFpIcon) {
            mAodFp.setVisibility(View.INVISIBLE);
            mAodFp.setContentDescription(null);
        }

        if (!Objects.equals(prevContentDescription, mView.getContentDescription())
                && mView.getContentDescription() != null) {
            mView.announceForAccessibility(mView.getContentDescription());
@@ -340,10 +375,12 @@ public class LockIconViewController extends ViewController<LockIconView> impleme

    @Override
    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
        pw.println("mUdfpsSupported: " + mUdfpsSupported);
        pw.println("mUdfpsEnrolled: " + mUdfpsEnrolled);
        pw.println("mIsKeyguardShowing: " + mIsKeyguardShowing);
        pw.println(" mShowUnlockIcon: " + mShowUnlockIcon);
        pw.println(" mShowLockIcon: " + mShowLockIcon);
        pw.println(" mShowAODFpIcon: " + mShowAODFpIcon);
        pw.println("  mIsDozing: " + mIsDozing);
        pw.println("  mIsBouncerShowing: " + mIsBouncerShowing);
        pw.println("  mUserUnlockedWithBiometric: " + mUserUnlockedWithBiometric);
@@ -351,17 +388,57 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
        pw.println("  mCanDismissLockScreen: " + mCanDismissLockScreen);
        pw.println("  mStatusBarState: " + StatusBarState.toShortString(mStatusBarState));
        pw.println("  mQsExpanded: " + mQsExpanded);
        pw.println("  mInterpolatedDarkAmount: " + mInterpolatedDarkAmount);

        if (mView != null) {
            mView.dump(fd, pw, args);
        }
    }

    /** Every minute, update the aod icon's burn in offset */
    public void dozeTimeTick() {
        updateBurnInOffsets();
    }

    private void updateBurnInOffsets() {
        float offsetX = MathUtils.lerp(0f,
                getBurnInOffset(mMaxBurnInOffsetX * 2, true /* xAxis */)
                        - mMaxBurnInOffsetX, mInterpolatedDarkAmount);
        float offsetY = MathUtils.lerp(0f,
                getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
                        - mMaxBurnInOffsetY, mInterpolatedDarkAmount);
        float progress = MathUtils.lerp(0f, getBurnInProgressOffset(), mInterpolatedDarkAmount);

        mAodFp.setTranslationX(offsetX);
        mAodFp.setTranslationY(offsetY);
        mAodFp.setProgress(progress);
        mAodFp.setAlpha(255 * mInterpolatedDarkAmount);
    }

    private void updateIsUdfpsEnrolled() {
        boolean wasUdfpsSupported = mUdfpsSupported;
        boolean wasUdfpsEnrolled = mUdfpsEnrolled;

        mUdfpsSupported = mAuthController.getUdfpsSensorLocation() != null;
        mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled();
        if (wasUdfpsSupported != mUdfpsSupported || wasUdfpsEnrolled != mUdfpsEnrolled) {
            updateVisibility();
        }
    }

    private StatusBarStateController.StateListener mStatusBarStateListener =
            new StatusBarStateController.StateListener() {
                @Override
                public void onDozeAmountChanged(float linear, float eased) {
                    mInterpolatedDarkAmount = eased;
                    updateBurnInOffsets();
                }

                @Override
                public void onDozingChanged(boolean isDozing) {
                    mIsDozing = isDozing;
                    updateBurnInOffsets();
                    updateIsUdfpsEnrolled();
                    updateVisibility();
                }

@@ -435,7 +512,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
                    mKeyguardUpdateMonitor.getUserUnlockedWithBiometric(
                        KeyguardUpdateMonitor.getCurrentUser());
            }
            mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled();
            updateIsUdfpsEnrolled();
            updateVisibility();
        }

@@ -481,8 +558,7 @@ public class LockIconViewController extends ViewController<LockIconView> impleme

                    // intercept all following touches until we see MotionEvent.ACTION_CANCEL UP or
                    // MotionEvent.ACTION_UP (see #onTouchEvent)
                    mDownDetected = true;
                    if (mVibrator != null) {
                    if (mVibrator != null && !mDownDetected) {
                        mVibrator.vibrate(
                                Process.myUid(),
                                getContext().getOpPackageName(),
@@ -490,6 +566,8 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
                                "lockIcon-onDown",
                                VIBRATION_SONIFICATION_ATTRIBUTES);
                    }

                    mDownDetected = true;
                    return true;
                }

@@ -544,6 +622,9 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
                    // pre-emptively set to true to hide view
                    mIsBouncerShowing = true;
                    updateVisibility();
                    if (mOnGestureDetectedRunnable != null) {
                        mOnGestureDetectedRunnable.run();
                    }
                    mKeyguardViewController.showBouncer(/* scrim */ true);
                    return true;
                }
@@ -554,16 +635,18 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
     * in a 'clickable' state
     * @return whether to intercept the touch event
     */
    public boolean onTouchEvent(MotionEvent event) {
    public boolean onTouchEvent(MotionEvent event, Runnable onGestureDetectedRunnable) {
        if (mSensorTouchLocation.contains((int) event.getX(), (int) event.getY())
                && mView.getVisibility() == View.VISIBLE) {
                && (mView.getVisibility() == View.VISIBLE
                || mAodFp.getVisibility() == View.VISIBLE)) {
            mOnGestureDetectedRunnable = onGestureDetectedRunnable;
            mGestureDetector.onTouchEvent(event);
        }

        // we continue to intercept all following touches until we see MotionEvent.ACTION_CANCEL UP
        // or MotionEvent.ACTION_UP. this is to avoid passing the touch to NPV
        // after the lock icon disappears on device entry
        if (mDownDetected && mDetectedLongPress) {
        if (mDownDetected) {
            if (event.getAction() == MotionEvent.ACTION_CANCEL
                    || event.getAction() == MotionEvent.ACTION_UP) {
                mDownDetected = false;
@@ -583,4 +666,12 @@ public class LockIconViewController extends ViewController<LockIconView> impleme
    public void setAlpha(float alpha) {
        mView.setAlpha(alpha);
    }

    private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
        @Override
        public void onAllAuthenticatorsRegistered() {
            updateIsUdfpsEnrolled();
            updateConfiguration();
        }
    };
}
+4 −0
Original line number Diff line number Diff line
@@ -848,6 +848,10 @@ public class UdfpsController implements DozeReceiver {
            return;
        }

        if (!mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
            return;
        }

        mAodInterruptRunnable = () -> {
            mIsAodInterruptActive = true;
            // Since the sensor that triggers the AOD interrupt doesn't provide
+0 −1
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@ import com.android.systemui.util.concurrency.DelayableExecutor;
import java.io.FileDescriptor;
import java.io.PrintWriter;


/**
 * Class that coordinates non-HBM animations during keyguard authentication.
 */
Loading