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

Commit 19be74dd authored by Austin Delgado's avatar Austin Delgado
Browse files

Fix race condition in UdfpsKeyguardView init

- Fixes the NPE crash when auth starts/stops repeatedly
- Fixes the UDFPS icon occasionally exploding in size

Bug: 263741015
Bug: 261519205
Test: atest SystemUITests:com.android.systemui.biometrics
Change-Id: I5f82d6bdb1f0d2e6c6660ebe9bf861d14ffcac30
parent a0f082aa
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -262,7 +262,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
            }
            REASON_AUTH_KEYGUARD -> {
                UdfpsKeyguardViewController(
                    view.addUdfpsView(R.layout.udfps_keyguard_view),
                    view.addUdfpsView(R.layout.udfps_keyguard_view) {
                        updateSensorLocation(sensorBounds)
                    },
                    statusBarStateController,
                    shadeExpansionStateManager,
                    statusBarKeyguardViewManager,
+1 −4
Original line number Diff line number Diff line
@@ -68,10 +68,7 @@ public class UdfpsEnrollViewController extends UdfpsAnimationViewController<Udfp
        mEnrollHelper = enrollHelper;
        mView.setEnrollHelper(mEnrollHelper);
        mView.setProgressBarRadius(mEnrollProgressBarRadius);

        if (featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION)) {
            mView.mUseExpandedOverlay = true;
        }
        mView.mUseExpandedOverlay = featureFlags.isEnabled(Flags.UDFPS_NEW_TOUCH_DETECTION);
    }

    @Override
+17 −21
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.MathUtils;
@@ -34,6 +35,7 @@ import android.view.ViewGroup;
import android.widget.ImageView;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.asynclayoutinflater.view.AsyncLayoutInflater;

@@ -65,6 +67,7 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
    private AnimatorSet mBackgroundInAnimator = new AnimatorSet();
    private int mAlpha; // 0-255
    private float mScaleFactor = 1;
    private Rect mSensorBounds = new Rect();

    // AOD anti-burn-in offsets
    private final int mMaxBurnInOffsetX;
@@ -76,8 +79,6 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
    private int mAnimationType = ANIMATION_NONE;
    private boolean mFullyInflated;

    private LayoutParams mParams;

    public UdfpsKeyguardView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mFingerprintDrawable = new UdfpsFpDrawable(context);
@@ -88,10 +89,7 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
            .getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

    public void startIconAsyncInflate() {
        // inflate Lottie views on a background thread in case it takes a while to inflate
        AsyncLayoutInflater inflater = new AsyncLayoutInflater(mContext);
        inflater.inflate(R.layout.udfps_keyguard_view_internal, this,
@@ -242,20 +240,8 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
        updateAlpha();
    }

    @Override
    void onSensorRectUpdated(RectF bounds) {
        super.onSensorRectUpdated(bounds);

        if (mUseExpandedOverlay) {
            mParams = new LayoutParams((int) bounds.width(), (int) bounds.height());
            RectF converted = getBoundsRelativeToView(bounds);
            mParams.setMargins(
                    (int) converted.left,
                    (int) converted.top,
                    (int) converted.right,
                    (int) converted.bottom
            );
        }
    void updateSensorLocation(@NonNull Rect sensorBounds) {
        mSensorBounds.set(sensorBounds);
    }

    /**
@@ -313,7 +299,17 @@ public class UdfpsKeyguardView extends UdfpsAnimationView {
            updateAlpha();

            if (mUseExpandedOverlay) {
                parent.addView(view, mParams);
                final LayoutParams lp = (LayoutParams) view.getLayoutParams();
                lp.width = mSensorBounds.width();
                lp.height = mSensorBounds.height();
                RectF relativeToView = getBoundsRelativeToView(new RectF(mSensorBounds));
                lp.setMargins(
                        (int) relativeToView.left,
                        (int) relativeToView.top,
                        (int) relativeToView.right,
                        (int) relativeToView.bottom
                );
                parent.addView(view, lp);
            } else {
                parent.addView(view);
            }
+1 −0
Original line number Diff line number Diff line
@@ -334,6 +334,7 @@ constructor(
        lockScreenShadeTransitionController.udfpsKeyguardViewController = this
        activityLaunchAnimator.addListener(activityLaunchAnimatorListener)
        view.mUseExpandedOverlay = useExpandedOverlay
        view.startIconAsyncInflate()
    }

    override fun onViewDetached() {
+6 −2
Original line number Diff line number Diff line
@@ -105,6 +105,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    @Mock private lateinit var udfpsController: UdfpsController
    @Mock private lateinit var udfpsView: UdfpsView
    @Mock private lateinit var udfpsEnrollView: UdfpsEnrollView
    @Mock private lateinit var udfpsKeyguardView: UdfpsKeyguardView
    @Mock private lateinit var activityLaunchAnimator: ActivityLaunchAnimator
    @Mock private lateinit var featureFlags: FeatureFlags
    @Mock private lateinit var primaryBouncerInteractor: PrimaryBouncerInteractor
@@ -125,7 +126,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        whenever(inflater.inflate(R.layout.udfps_bp_view, null))
            .thenReturn(mock(UdfpsBpView::class.java))
        whenever(inflater.inflate(R.layout.udfps_keyguard_view, null))
            .thenReturn(mock(UdfpsKeyguardView::class.java))
            .thenReturn(udfpsKeyguardView)
        whenever(inflater.inflate(R.layout.udfps_fpm_empty_view, null))
            .thenReturn(mock(UdfpsFpmEmptyView::class.java))
        whenever(udfpsEnrollView.context).thenReturn(context)
@@ -152,7 +153,10 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    fun showUdfpsOverlay_bp() = withReason(REASON_AUTH_BP) { showUdfpsOverlay() }

    @Test
    fun showUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) { showUdfpsOverlay() }
    fun showUdfpsOverlay_keyguard() = withReason(REASON_AUTH_KEYGUARD) {
        showUdfpsOverlay()
        verify(udfpsKeyguardView).updateSensorLocation(eq(overlayParams.sensorBounds))
    }

    @Test
    fun showUdfpsOverlay_settings() = withReason(REASON_AUTH_SETTINGS) { showUdfpsOverlay() }