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

Commit 4a70d725 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Always cancel insets animation if control target is gone

Otherwise if updateControlForTarget is called when consuming
mHasPendingPosition with mPendingControlTarget==null in
mSetControlPositionConsumer, there could be NPE that mControl
is set to null from notifyControlTargetChanged.

Besides, it is unnecessary to handle position by
mSetControlPositionConsumer if the control target is gone.
So simply cancel the animation rather than adding null check.

Fix: 433587055
Flag: EXEMPT bugfix
Test: InsetsSourceProviderTest#testUpdateControlForTarget
Change-Id: Ia8e34bc583278c691f053ea07f375a451854e789
parent 431671f1
Loading
Loading
Loading
Loading
+6 −5
Original line number Diff line number Diff line
@@ -492,17 +492,18 @@ class InsetsSourceProvider {
        if (target == mControlTarget && !force) {
            return;
        }
        if (mHasPendingPosition) {
            // Don't create a new leash while having a pending position. Otherwise, the position
            // will be changed earlier than expected, which can cause flicker.
            return;
        }
        if (target == null) {
            mHasPendingPosition = false;
            // Cancelling the animation will invoke onAnimationCancelled, resetting all the fields.
            mWin.cancelAnimation();
            setClientVisible((WindowInsets.Type.defaultVisible() & mSource.getType()) != 0);
            return;
        }
        if (mHasPendingPosition) {
            // Don't create a new leash while having a pending position. Otherwise, the position
            // will be changed earlier than expected, which can cause flicker.
            return;
        }
        boolean initiallyVisible = mClientVisible;
        final Point surfacePosition = getWindowFrameSurfacePosition(mWin);
        mPosition.set(surfacePosition);
+19 −0
Original line number Diff line number Diff line
@@ -22,6 +22,9 @@ import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
@@ -34,6 +37,7 @@ import android.graphics.Point;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.view.InsetsSource;
import android.view.SurfaceControl;

import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
@@ -143,10 +147,25 @@ public class InsetsSourceProviderTest extends WindowTestsBase {

        // We must not have control or control target if the insets source window doesn't have a
        // surface.
        final SurfaceControl sc = statusBar.mSurfaceControl;
        statusBar.setSurfaceControl(null);
        mProvider.updateControlForTarget(target, true /* force */, null /* statsToken */);
        assertNull(mProvider.getControl(target));
        assertNull(mProvider.getControlTarget());

        // Verifies that the control is revoked immediately if the target becomes null even if
        // InsetsSourceProvider#mHasPendingPosition is true.
        statusBar.setSurfaceControl(sc);
        mProvider.setWindow(statusBar, null, null);
        mProvider.updateControlForTarget(target, false /* force */, null /* statsToken */);
        assertNotNull(statusBar.getAnimationLeash());
        statusBar.getFrame().offset(100, 100);
        spyOn(statusBar.mWinAnimator);
        doReturn(true).when(statusBar.mWinAnimator).getShown();
        mProvider.updateInsetsControlPosition(statusBar);
        assertTrue(statusBar.shouldSyncWithBuffers());
        mProvider.updateControlForTarget(null, false /* force */, null /* statsToken */);
        assertNull(statusBar.getAnimationLeash());
    }

    @Test