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

Commit e0a5469c authored by Peter Cai's avatar Peter Cai Committed by Łukasz Patron
Browse files

FODCircleView: defer removal to next re-layout

* Originally, when hide() is called, it removes the dim layer and then
  removes the view immediately, then calls the hide event in HAL. This
  causes severe flickering because the HAL is expected to restore the
  brightness immediately, but the dim layer will not be removed until
  the next repaint cycle.

* Since it is not easy to listen for a redraw after the view itself has
  been removed, we can defer removal after the next time onLayout() is
  called. When tested on my OnePlus 7 Pro, this reduces flickering on
  successful fp authentication drastically.

* There are some cases where show() is called so quickly after hide()
  that the view hasn't been actually removed due to this change (which
  is actually another cause of flickering). This is handled by checking
  the removal flag in show() and removing it immediately if the view is
  yet to be removed, and also by moving calls to HAL show / hide events
  to the actual attached / detached event handlers.

* For consistency in semantics, also move calls related to the dim
  layer that were originally in onDraw for similar reasons to the
  onLayout function.

Change-Id: I9b0cfe5c4d572a64b918ce7d3c130a659fd25a30
parent 7b13c0f5
Loading
Loading
Loading
Loading
+56 −23
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ public class FODCircleView extends ImageView implements OnTouchListener {
    private boolean mIsPulsing;
    private boolean mIsScreenOn;
    private boolean mIsViewAdded;
    private boolean mIsRemoving;

    private Handler mHandler;

@@ -244,6 +245,20 @@ public class FODCircleView extends ImageView implements OnTouchListener {
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (mIsInsideCircle) {
            canvas.drawCircle(mWidth / 2, mHeight / 2, (float) (mWidth / 2.0f), mPaintFingerprint);
        }
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);

        // onLayout is a good time to call the HAL because dim layer
        // added by setDim() should have come into effect
        // the HAL is expected (if supported) to set the screen brightness
        // to maximum / minimum immediately when called
        if (mIsInsideCircle) {
            if (mIsDreaming) {
                setAlpha(1.0f);
@@ -259,7 +274,6 @@ public class FODCircleView extends ImageView implements OnTouchListener {
                }
                mIsPressed = true;
            }
            canvas.drawCircle(mWidth / 2, mHeight / 2, (float) (mWidth / 2.0f), mPaintFingerprint);
        } else {
            setAlpha(mIsDreaming ? 0.5f : 1.0f);
            if (mIsPressed) {
@@ -273,6 +287,11 @@ public class FODCircleView extends ImageView implements OnTouchListener {
                }
                mIsPressed = false;
            }

            if (mIsRemoving) {
                mIsRemoving = false;
                mWindowManager.removeView(this);
            }
        }
    }

@@ -318,6 +337,33 @@ public class FODCircleView extends ImageView implements OnTouchListener {
        }
    }

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

        IFingerprintInscreen daemon = getFingerprintInScreenDaemon();
        if (daemon != null) {
            try {
                daemon.onHideFODView();
            } catch (RemoteException e) {
                // do nothing
            }
        }
    }

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

        IFingerprintInscreen daemon = getFingerprintInScreenDaemon();
        if (daemon != null) {
            try {
                daemon.onShowFODView();
            } catch (RemoteException e) {
                // do nothing
            }
        }
    }

    public synchronized IFingerprintInscreen getFingerprintInScreenDaemon() {
        if (mFingerprintInscreenDaemon == null) {
@@ -337,6 +383,12 @@ public class FODCircleView extends ImageView implements OnTouchListener {
    }

    public void show() {
        if (mIsRemoving) {
            // Last removal hasn't been finished yet
            mIsRemoving = false;
            mWindowManager.removeView(this);
        }

        if (mIsViewAdded) {
            return;
        }
@@ -367,15 +419,6 @@ public class FODCircleView extends ImageView implements OnTouchListener {

        mIsPressed = false;
        setDim(false);

        IFingerprintInscreen daemon = getFingerprintInScreenDaemon();
        if (daemon != null) {
            try {
                daemon.onShowFODView();
            } catch (RemoteException e) {
                // do nothing
            }
        }
    }

    public void hide() {
@@ -384,21 +427,11 @@ public class FODCircleView extends ImageView implements OnTouchListener {
        }

        mIsInsideCircle = false;

        mWindowManager.removeView(this);
        mIsViewAdded = false;

        mIsPressed = false;
        // Postpone removal to next re-layout to avoid blinking
        mIsRemoving = true;
        setDim(false);

        IFingerprintInscreen daemon = getFingerprintInScreenDaemon();
        if (daemon != null) {
            try {
                daemon.onHideFODView();
            } catch (RemoteException e) {
                // do nothing
            }
        }
        invalidate();
    }

    private void resetPosition() {