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

Commit 93a5ab7f authored by Jeff DeCew's avatar Jeff DeCew Committed by Yining Liu
Browse files

ViewFlipper: add inhibit state to prevent updates, even when started

This internal state avoids a potential race condition in how SystemUI previously paused the ViewFlipper, which could have happened if the `setPaused` call was made before the view received the internal `onAttachedToView` update that would trigger auto-start.  This race was never confirmed, but this refactor should prevent it.

Test: manual with tracing
Bug: 409112153
Flag: EXEMPT refactor
Change-Id: Ie1d76a5eec753dd25b91fb29f7bb5dfed8a7b40c
parent a59184b4
Loading
Loading
Loading
Loading
+21 −2
Original line number Diff line number Diff line
@@ -49,6 +49,9 @@ public class ViewFlipper extends ViewAnimator {
    private boolean mStarted = false;
    private boolean mVisible = false;

    // Inhibiting prevents the view from actually animating, even if started or auto-started.
    private boolean mInhibited = false;

    public ViewFlipper(Context context) {
        super(context);
    }
@@ -127,6 +130,22 @@ public class ViewFlipper extends ViewAnimator {
        updateRunning();
    }

    /**
     * Inhibits the view from actually animating, even if it is started or auto-started.
     *
     * <p>NOTE: This state is NOT reflected in the {@link #isFlipping()} method. That method
     * returns true if the view is started or auto-started, even if inhibited. There is no way to
     * inspect the inhibited state, and it is only intended to be a override to prevent the
     * ViewFlipper from updating in cases where the system knows the view is not visible, but the
     * view does not.
     *
     * @hide
     */
    public void setInhibited(boolean inhibited) {
        mInhibited = inhibited;
        updateRunning();
    }

    @Override
    public CharSequence getAccessibilityClassName() {
        return ViewFlipper.class.getName();
@@ -150,7 +169,7 @@ public class ViewFlipper extends ViewAnimator {
     */
    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
    private void updateRunning(boolean flipNow) {
        boolean running = mVisible && mStarted;
        boolean running = mVisible && mStarted && !mInhibited;
        if (running != mRunning) {
            if (running) {
                showOnly(mWhichChild, flipNow);
@@ -162,7 +181,7 @@ public class ViewFlipper extends ViewAnimator {
        }
        if (LOGD) {
            Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
                    + ", mRunning=" + mRunning);
                    + ", mInhibited=" + mInhibited + ", mRunning=" + mRunning);
        }
    }

+1 −9
Original line number Diff line number Diff line
@@ -42,13 +42,5 @@ object NotificationViewFlipperBinder {
    suspend fun bind(
        viewFlipper: ViewFlipper,
        viewModel: NotificationViewFlipperViewModel,
    ) = coroutineScope { launch { viewModel.isPaused.collect { viewFlipper.setPaused(it) } } }

    private fun ViewFlipper.setPaused(paused: Boolean) {
        if (paused) {
            stopFlipping()
        } else if (isAutoStart) {
            startFlipping()
        }
    }
    ) = coroutineScope { launch { viewModel.isPaused.collect { viewFlipper.setInhibited(it) } } }
}