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

Commit 5d84ef9b authored by Kazuki Takise's avatar Kazuki Takise
Browse files

Don't offset the position of the thumbnail in change transitions

There are two adaptors used for change transitions: mAdapter and
mThumbnailAdapter. The position and crop of the leashe in the
adapters are adjusted to the start bounds when the a transition
starts, and currently the same value is used for mAdapter and
mThumbnailAdapter. The problem here is, as the thumbnail is a child
of the window of |mAdapter|, the thumbnail gets double offseted
incrrectly, which results in the snapshot being shown at an
incorrect position until the client starts the animation and
modifies the position.

This CL lets RemoteAnimationController give each adapter its
explicit start bounds.

Bug: 159294946
Test: No buffer jump in change transitions anymore.
Change-Id: I1dafd5587ed7c9b628d8f1f40a2559ec3e9a63d5
parent fa6332bb
Loading
Loading
Loading
Loading
+13 −9
Original line number Original line Diff line number Diff line
@@ -359,17 +359,20 @@ class RemoteAnimationController implements DeathRecipient {
        RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds,
        RemoteAnimationRecord(WindowContainer windowContainer, Point endPos, Rect localBounds,
                Rect endBounds, Rect startBounds) {
                Rect endBounds, Rect startBounds) {
            mWindowContainer = windowContainer;
            mWindowContainer = windowContainer;
            mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds);
            if (startBounds != null) {
            if (startBounds != null) {
                mStartBounds = new Rect(startBounds);
                mStartBounds = new Rect(startBounds);
                mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
                        mStartBounds);
                mTmpRect.set(startBounds);
                mTmpRect.set(startBounds);
                mTmpRect.offsetTo(0, 0);
                mTmpRect.offsetTo(0, 0);
                if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
                if (mRemoteAnimationAdapter.getChangeNeedsSnapshot()) {
                    mThumbnailAdapter =
                    mThumbnailAdapter =
                            new RemoteAnimationAdapterWrapper(this, new Point(0, 0), localBounds,
                            new RemoteAnimationAdapterWrapper(this, new Point(0, 0), localBounds,
                                    mTmpRect);
                                    mTmpRect, new Rect());
                }
                }
            } else {
            } else {
                mAdapter = new RemoteAnimationAdapterWrapper(this, endPos, localBounds, endBounds,
                        new Rect(endPos.x, endPos.y, endBounds.right, endBounds.bottom));
                mStartBounds = null;
                mStartBounds = null;
            }
            }
        }
        }
@@ -407,13 +410,15 @@ class RemoteAnimationController implements DeathRecipient {
        final Point mPosition = new Point();
        final Point mPosition = new Point();
        final Rect mLocalBounds;
        final Rect mLocalBounds;
        final Rect mStackBounds = new Rect();
        final Rect mStackBounds = new Rect();
        final Rect mStartBounds = new Rect();


        RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
        RemoteAnimationAdapterWrapper(RemoteAnimationRecord record, Point position,
                Rect localBounds, Rect stackBounds) {
                Rect localBounds, Rect stackBounds, Rect startBounds) {
            mRecord = record;
            mRecord = record;
            mPosition.set(position.x, position.y);
            mPosition.set(position.x, position.y);
            mLocalBounds = localBounds;
            mLocalBounds = localBounds;
            mStackBounds.set(stackBounds);
            mStackBounds.set(stackBounds);
            mStartBounds.set(startBounds);
        }
        }


        @Override
        @Override
@@ -427,13 +432,12 @@ class RemoteAnimationController implements DeathRecipient {
            ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");
            ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation");


            // Restore position and stack crop until client has a chance to modify it.
            // Restore position and stack crop until client has a chance to modify it.
            if (mRecord.mStartBounds != null) {
            if (mStartBounds.isEmpty()) {
                t.setPosition(animationLeash, mRecord.mStartBounds.left, mRecord.mStartBounds.top);
                t.setPosition(animationLeash, 0, 0);
                t.setWindowCrop(animationLeash, mRecord.mStartBounds.width(),
                t.setWindowCrop(animationLeash, -1, -1);
                        mRecord.mStartBounds.height());
            } else {
            } else {
                t.setPosition(animationLeash, mPosition.x, mPosition.y);
                t.setPosition(animationLeash, mStartBounds.left, mStartBounds.top);
                t.setWindowCrop(animationLeash, mStackBounds.width(), mStackBounds.height());
                t.setWindowCrop(animationLeash, mStartBounds.width(), mStartBounds.height());
            }
            }
            mCapturedLeash = animationLeash;
            mCapturedLeash = animationLeash;
            mCapturedFinishCallback = finishCallback;
            mCapturedFinishCallback = finishCallback;
+55 −3
Original line number Original line Diff line number Diff line
@@ -46,7 +46,6 @@ import android.view.RemoteAnimationTarget;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceControl.Transaction;


import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import androidx.test.filters.SmallTest;


import com.android.server.testutils.OffsettableClock;
import com.android.server.testutils.OffsettableClock;
@@ -244,7 +243,7 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
    }
    }


    @Test
    @Test
    public void testChange() throws Exception {
    public void testChangeToSmallerSize() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mChangingContainers.add(win.mActivityRecord);
        mDisplayContent.mChangingContainers.add(win.mActivityRecord);
        try {
        try {
@@ -279,8 +278,61 @@ public class RemoteAnimationControllerTest extends WindowTestsBase {
            assertEquals(false, app.isTranslucent);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(
            verify(mMockTransaction).setPosition(
                    mMockLeash, app.startBounds.left, app.startBounds.top);
                    mMockLeash, app.startBounds.left, app.startBounds.top);
            verify(mMockTransaction).setWindowCrop(mMockLeash, 200, 200);
            verify(mMockTransaction).setWindowCrop(
                    mMockLeash, app.startBounds.width(), app.startBounds.height());
            verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
            verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
            verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, -1, -1);

            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
                    eq(record.mAdapter));
            verify(mThumbnailFinishedCallback).onAnimationFinished(
                    eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
        } finally {
            mDisplayContent.mChangingContainers.clear();
        }
    }

    @Test
    public void testChangeTolargerSize() throws Exception {
        final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
        mDisplayContent.mChangingContainers.add(win.mActivityRecord);
        try {
            final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
                    win.mActivityRecord, new Point(0, 0), null, new Rect(0, 0, 200, 200),
                    new Rect(50, 100, 150, 150));
            assertNotNull(record.mThumbnailAdapter);
            ((AnimationAdapter) record.mAdapter)
                    .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
                            mFinishedCallback);
            ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
                    mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
            mController.goodToGo();
            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
            final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
                    ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
            final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
                    ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
            verify(mMockRunner).onAnimationStart(appsCaptor.capture(), wallpapersCaptor.capture(),
                    finishedCaptor.capture());
            assertEquals(1, appsCaptor.getValue().length);
            final RemoteAnimationTarget app = appsCaptor.getValue()[0];
            assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
            assertEquals(new Point(0, 0), app.position);
            assertEquals(new Rect(0, 0, 200, 200), app.sourceContainerBounds);
            assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
            assertEquals(mMockLeash, app.leash);
            assertEquals(mMockThumbnailLeash, app.startLeash);
            assertEquals(win.mWinAnimator.mLastClipRect, app.clipRect);
            assertEquals(false, app.isTranslucent);
            verify(mMockTransaction).setPosition(
                    mMockLeash, app.startBounds.left, app.startBounds.top);
            verify(mMockTransaction).setWindowCrop(
                    mMockLeash, app.startBounds.width(), app.startBounds.height());
            verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
            verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, -1, -1);


            finishedCaptor.getValue().onAnimationFinished();
            finishedCaptor.getValue().onAnimationFinished();
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
            verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),