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

Commit 19c7260b authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Make sure that animation leash is removed with window container

Unlike ActivityRecord and WindowState, the general window container
doesn't clean up its animation for removal. So if the container is
removed while animating, the animation leash surface may be leaked.

One case is that when rotating display with a short life window such
as Toast, the the leash created by FadeRotationAnimationController
may remain on DisplayArea (the parent of WindowToken).

Bug: 212483446
Test: atest WindowContainerTests#testRemoveImmediatelyClearsLeash
Change-Id: I1b4833b14a3c6c4ea1338156f5bfd7bf475645d1
parent 1b31769f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -387,6 +387,8 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<

        if (mParent != null) {
            mParent.onChildAdded(this);
        } else if (mSurfaceAnimator.hasLeash()) {
            mSurfaceAnimator.cancelAnimation();
        }
        if (!mReparenting) {
            onSyncReparent(oldParent, mParent);
+1 −2
Original line number Diff line number Diff line
@@ -117,8 +117,7 @@ public class RecentsAnimationControllerTest extends WindowTestsBase {
        adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_RECENTS,
                mFinishedCallback);

        // Remove the app window so that the animation target can not be created
        activity.removeImmediately();
        // The activity doesn't contain window so the animation target cannot be created.
        mController.startAnimation();

        // Verify that the finish callback to reparent the leash is called
+18 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
@@ -77,6 +78,7 @@ import androidx.test.filters.SmallTest;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;

import java.util.ArrayList;
@@ -270,6 +272,22 @@ public class WindowContainerTests extends WindowTestsBase {
        }
    }

    @Test
    public void testRemoveImmediatelyClearsLeash() {
        final AnimationAdapter animAdapter = mock(AnimationAdapter.class);
        final WindowToken token = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
        final SurfaceControl.Transaction t = token.getPendingTransaction();
        token.startAnimation(t, animAdapter, false /* hidden */,
                SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION);
        final ArgumentCaptor<SurfaceControl> leashCaptor =
                ArgumentCaptor.forClass(SurfaceControl.class);
        verify(animAdapter).startAnimation(leashCaptor.capture(), eq(t), anyInt(), any());
        assertTrue(token.mSurfaceAnimator.hasLeash());
        token.removeImmediately();
        assertFalse(token.mSurfaceAnimator.hasLeash());
        verify(t).remove(eq(leashCaptor.getValue()));
    }

    @Test
    public void testAddChildByIndex() {
        final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);