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

Commit 6c934231 authored by Perry Wu's avatar Perry Wu Committed by Android (Google) Code Review
Browse files

Merge "[PIP2] Enable rounded corners" into main

parents 16e029a9 2ad57bfe
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -52,6 +52,9 @@ public class PipEnterAnimator extends ValueAnimator {
    private final SurfaceControl.Transaction mStartTransaction;
    private final SurfaceControl.Transaction mFinishTransaction;

    private final int mCornerRadius;
    private final int mShadowRadius;

    // Bounds updated by the evaluator as animator is running.
    private final Rect mAnimatedRect = new Rect();

@@ -128,6 +131,8 @@ public class PipEnterAnimator extends ValueAnimator {

        final int enterAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipEnterAnimationDuration);
        mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
        mShadowRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);
        setDuration(enterAnimationDuration);
        setFloatValues(0f, 1f);
        setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
@@ -177,6 +182,8 @@ public class PipEnterAnimator extends ValueAnimator {
        mTransformTensor.postRotate(degrees);
        tx.setMatrix(mLeash, mTransformTensor, mMatrixTmp);

        tx.setCornerRadius(mLeash, mCornerRadius).setShadowRadius(mLeash, mShadowRadius);

        if (mContentOverlay != null) {
            mContentOverlay.onAnimationUpdate(tx, 1f / scaleX, fraction, mEndBounds);
        }
+17 −5
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
import com.android.wm.shell.shared.animation.Interpolators;

@@ -50,6 +51,9 @@ public class PipResizeAnimator extends ValueAnimator {
    private Runnable mAnimationEndCallback;
    private RectEvaluator mRectEvaluator;

    private final int mCornerRadius;
    private final int mShadowRadius;

    // Bounds relative to which scaling/cropping must be done.
    private final Rect mBaseBounds = new Rect();

@@ -74,7 +78,8 @@ public class PipResizeAnimator extends ValueAnimator {
                mAnimationStartCallback.run();
            }
            if (mStartTx != null) {
                setBoundsAndRotation(mStartTx, mLeash, mBaseBounds, mStartBounds, mDelta);
                setBoundsAndRotation(mStartTx, mLeash, mBaseBounds, mStartBounds, mDelta,
                        mCornerRadius, mShadowRadius);
                mStartTx.apply();
            }
        }
@@ -83,7 +88,8 @@ public class PipResizeAnimator extends ValueAnimator {
        public void onAnimationEnd(Animator animation) {
            super.onAnimationEnd(animation);
            if (mFinishTx != null) {
                setBoundsAndRotation(mFinishTx, mLeash, mBaseBounds, mEndBounds, 0f);
                setBoundsAndRotation(mFinishTx, mLeash, mBaseBounds, mEndBounds, 0f,
                        mCornerRadius, mShadowRadius);
            }
            if (mAnimationEndCallback != null) {
                mAnimationEndCallback.run();
@@ -99,7 +105,8 @@ public class PipResizeAnimator extends ValueAnimator {
                            mSurfaceControlTransactionFactory.getTransaction();
                    final float fraction = getAnimatedFraction();
                    final float degrees = (1.0f - fraction) * mDelta;
                    setBoundsAndRotation(tx, mLeash, mBaseBounds, mAnimatedRect, degrees);
                    setBoundsAndRotation(tx, mLeash, mBaseBounds, mAnimatedRect, degrees,
                            mCornerRadius, mShadowRadius);
                    tx.apply();
                }
            };
@@ -128,6 +135,9 @@ public class PipResizeAnimator extends ValueAnimator {

        mRectEvaluator = new RectEvaluator(mAnimatedRect);

        mCornerRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
        mShadowRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);

        setObjectValues(startBounds, endBounds);
        setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
        addListener(mAnimatorListener);
@@ -152,7 +162,7 @@ public class PipResizeAnimator extends ValueAnimator {
     * @param degrees degrees of rotation - counter-clockwise is positive by convention.
     */
    private static void setBoundsAndRotation(SurfaceControl.Transaction tx, SurfaceControl leash,
            Rect baseBounds, Rect targetBounds, float degrees) {
            Rect baseBounds, Rect targetBounds, float degrees, int cornerRadius, int shadowRadius) {
        Matrix transformTensor = new Matrix();
        final float[] mMatrixTmp = new float[9];
        final float scaleX = (float) targetBounds.width() / baseBounds.width();
@@ -162,7 +172,9 @@ public class PipResizeAnimator extends ValueAnimator {
        transformTensor.postTranslate(targetBounds.left, targetBounds.top);
        transformTensor.postRotate(degrees, targetBounds.centerX(), targetBounds.centerY());

        tx.setMatrix(leash, transformTensor, mMatrixTmp);
        tx.setMatrix(leash, transformTensor, mMatrixTmp)
                .setCornerRadius(leash, cornerRadius)
                .setShadowRadius(leash, shadowRadius);
    }

    @VisibleForTesting
+10 −2
Original line number Diff line number Diff line
@@ -785,8 +785,16 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,

    private void handleFlingTransition(SurfaceControl.Transaction startTx,
            SurfaceControl.Transaction finishTx, Rect destinationBounds) {
        startTx.setPosition(mPipTransitionState.getPinnedTaskLeash(),
                destinationBounds.left, destinationBounds.top);
        SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash();
        int cornerRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
        int shadowRadius = mContext.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);

        // merge transactions so everything is done on startTx
        startTx.merge(finishTx);

        startTx.setPosition(pipLeash, destinationBounds.left, destinationBounds.top)
                .setCornerRadius(pipLeash, cornerRadius)
                .setShadowRadius(pipLeash, shadowRadius);
        startTx.apply();

        // All motion operations have actually finished, so make bounds cache updates.
+41 −17
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@@ -39,6 +40,7 @@ import android.view.SurfaceControl;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.wm.shell.R;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;
import com.android.wm.shell.pip2.phone.PipAppIconOverlay;

@@ -49,33 +51,25 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/**
 * Unit test again {@link PipEnterAnimator}.
 * Unit test against {@link PipEnterAnimator}.
 */
@SmallTest
@TestableLooper.RunWithLooper
@RunWith(AndroidTestingRunner.class)
public class PipEnterAnimatorTest {
    private static final float TEST_CORNER_RADIUS = 1f;
    private static final float TEST_SHADOW_RADIUS = 2f;

    @Mock private Context mMockContext;

    @Mock private Resources mMockResources;

    @Mock private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mMockFactory;

    @Mock private SurfaceControl.Transaction mMockAnimateTransaction;

    @Mock private SurfaceControl.Transaction mMockStartTransaction;

    @Mock private SurfaceControl.Transaction mMockFinishTransaction;

    @Mock private Runnable mMockStartCallback;

    @Mock private Runnable mMockEndCallback;

    @Mock private PipAppIconOverlay mMockPipAppIconOverlay;

    @Mock private SurfaceControl mMockAppIconOverlayLeash;

    @Mock private ActivityInfo mMockActivityInfo;

    @Surface.Rotation private int mRotation;
@@ -89,13 +83,15 @@ public class PipEnterAnimatorTest {
        when(mMockContext.getResources()).thenReturn(mMockResources);
        when(mMockResources.getInteger(anyInt())).thenReturn(0);
        when(mMockFactory.getTransaction()).thenReturn(mMockAnimateTransaction);
        when(mMockAnimateTransaction.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(mMockAnimateTransaction);
        when(mMockStartTransaction.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(mMockStartTransaction);
        when(mMockFinishTransaction.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(mMockFinishTransaction);
        when(mMockPipAppIconOverlay.getLeash()).thenReturn(mMockAppIconOverlayLeash);
        when(mMockResources.getDimensionPixelSize(R.dimen.pip_corner_radius))
                .thenReturn((int) TEST_CORNER_RADIUS);
        when(mMockResources.getDimensionPixelSize(R.dimen.pip_shadow_radius))
                .thenReturn((int) TEST_SHADOW_RADIUS);

        prepareTransaction(mMockAnimateTransaction);
        prepareTransaction(mMockStartTransaction);
        prepareTransaction(mMockFinishTransaction);

        mTestLeash = new SurfaceControl.Builder()
                .setContainerLayer()
@@ -122,6 +118,12 @@ public class PipEnterAnimatorTest {

        verify(mMockStartCallback).run();
        verifyZeroInteractions(mMockEndCallback);

        // Check corner and shadow radii were set
        verify(mMockAnimateTransaction, atLeastOnce())
                .setCornerRadius(eq(mTestLeash), eq(TEST_CORNER_RADIUS));
        verify(mMockAnimateTransaction, atLeastOnce())
                .setShadowRadius(eq(mTestLeash), eq(TEST_SHADOW_RADIUS));
    }

    @Test
@@ -142,6 +144,12 @@ public class PipEnterAnimatorTest {

        verify(mMockStartCallback).run();
        verify(mMockEndCallback).run();

        // Check corner and shadow radii were set
        verify(mMockAnimateTransaction, atLeastOnce())
                .setCornerRadius(eq(mTestLeash), eq(TEST_CORNER_RADIUS));
        verify(mMockAnimateTransaction, atLeastOnce())
                .setShadowRadius(eq(mTestLeash), eq(TEST_SHADOW_RADIUS));
    }

    @Test
@@ -197,5 +205,21 @@ public class PipEnterAnimatorTest {

        verify(mMockPipAppIconOverlay).onAnimationUpdate(
                eq(mMockAnimateTransaction), anyFloat(), eq(fraction), eq(mEndBounds));

        // Check corner and shadow radii were set
        verify(mMockAnimateTransaction, atLeastOnce())
                .setCornerRadius(eq(mTestLeash), eq(TEST_CORNER_RADIUS));
        verify(mMockAnimateTransaction, atLeastOnce())
                .setShadowRadius(eq(mTestLeash), eq(TEST_SHADOW_RADIUS));
    }

    // set up transaction chaining
    private void prepareTransaction(SurfaceControl.Transaction tx) {
        when(tx.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(tx);
        when(tx.setCornerRadius(any(SurfaceControl.class), anyFloat()))
                .thenReturn(tx);
        when(tx.setShadowRadius(any(SurfaceControl.class), anyFloat()))
                .thenReturn(tx);
    }
}
+49 −16
Original line number Diff line number Diff line
@@ -16,15 +16,18 @@

package com.android.wm.shell.pip2.animation;

import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
import static org.mockito.kotlin.MatchersKt.eq;
import static org.junit.Assert.assertEquals;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
@@ -34,12 +37,14 @@ import android.view.SurfaceControl;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;

import com.android.wm.shell.R;
import com.android.wm.shell.pip2.PipSurfaceTransactionHelper;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@@ -52,40 +57,40 @@ import org.mockito.MockitoAnnotations;
public class PipResizeAnimatorTest {

    private static final float FLOAT_COMPARISON_DELTA = 0.001f;
    private static final float TEST_CORNER_RADIUS = 1f;
    private static final float TEST_SHADOW_RADIUS = 2f;

    @Mock private Context mMockContext;

    @Mock private Resources mMockResources;
    @Mock private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory mMockFactory;

    @Mock private SurfaceControl.Transaction mMockTransaction;

    @Mock private SurfaceControl.Transaction mMockStartTransaction;

    @Mock private SurfaceControl.Transaction mMockFinishTransaction;

    @Mock private Runnable mMockStartCallback;

    @Mock private Runnable mMockEndCallback;

    @Captor private ArgumentCaptor<Matrix> mArgumentCaptor;

    private PipResizeAnimator mPipResizeAnimator;
    private Rect mBaseBounds;
    private Rect mStartBounds;
    private Rect mEndBounds;
    private SurfaceControl mTestLeash;
    private ArgumentCaptor<Matrix> mArgumentCaptor;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        when(mMockFactory.getTransaction()).thenReturn(mMockTransaction);
        when(mMockTransaction.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(mMockTransaction);
        when(mMockStartTransaction.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(mMockStartTransaction);
        when(mMockFinishTransaction.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(mMockFinishTransaction);

        mArgumentCaptor = ArgumentCaptor.forClass(Matrix.class);
        when(mMockContext.getResources()).thenReturn(mMockResources);
        when(mMockResources.getDimensionPixelSize(R.dimen.pip_corner_radius))
                .thenReturn((int) TEST_CORNER_RADIUS);
        when(mMockResources.getDimensionPixelSize(R.dimen.pip_shadow_radius))
                .thenReturn((int) TEST_SHADOW_RADIUS);

        prepareTransaction(mMockTransaction);
        prepareTransaction(mMockStartTransaction);
        prepareTransaction(mMockFinishTransaction);

        mTestLeash = new SurfaceControl.Builder()
                .setContainerLayer()
                .setName("PipResizeAnimatorTest")
@@ -187,6 +192,12 @@ public class PipResizeAnimatorTest {
        assertEquals(matrix[Matrix.MSCALE_Y], 1f, FLOAT_COMPARISON_DELTA);
        assertEquals(matrix[Matrix.MTRANS_X], mEndBounds.left, FLOAT_COMPARISON_DELTA);
        assertEquals(matrix[Matrix.MTRANS_Y], mEndBounds.top, FLOAT_COMPARISON_DELTA);

        // Check corner and shadow radii were set
        verify(mMockTransaction, atLeastOnce())
                .setCornerRadius(eq(mTestLeash), eq(TEST_CORNER_RADIUS));
        verify(mMockTransaction, atLeastOnce())
                .setShadowRadius(eq(mTestLeash), eq(TEST_SHADOW_RADIUS));
    }

    @Test
@@ -237,6 +248,12 @@ public class PipResizeAnimatorTest {
        assertEquals(matrix[Matrix.MSCALE_Y], 1f, FLOAT_COMPARISON_DELTA);
        assertEquals(matrix[Matrix.MTRANS_X], mEndBounds.left, FLOAT_COMPARISON_DELTA);
        assertEquals(matrix[Matrix.MTRANS_Y], mEndBounds.top, FLOAT_COMPARISON_DELTA);

        // Check corner and shadow radii were set
        verify(mMockTransaction, atLeastOnce())
                .setCornerRadius(eq(mTestLeash), eq(TEST_CORNER_RADIUS));
        verify(mMockTransaction, atLeastOnce())
                .setShadowRadius(eq(mTestLeash), eq(TEST_SHADOW_RADIUS));
    }

    @Test
@@ -272,5 +289,21 @@ public class PipResizeAnimatorTest {
        mArgumentCaptor.getValue().getValues(matrix);
        assertEquals(matrix[Matrix.MSKEW_X], 0f, FLOAT_COMPARISON_DELTA);
        assertEquals(matrix[Matrix.MSKEW_Y], 0f, FLOAT_COMPARISON_DELTA);

        // Check corner and shadow radii were set
        verify(mMockTransaction, atLeastOnce())
                .setCornerRadius(eq(mTestLeash), eq(TEST_CORNER_RADIUS));
        verify(mMockTransaction, atLeastOnce())
                .setShadowRadius(eq(mTestLeash), eq(TEST_SHADOW_RADIUS));
    }

    // set up transaction chaining
    private void prepareTransaction(SurfaceControl.Transaction tx) {
        when(tx.setMatrix(any(SurfaceControl.class), any(Matrix.class), any()))
                .thenReturn(tx);
        when(tx.setCornerRadius(any(SurfaceControl.class), anyFloat()))
                .thenReturn(tx);
        when(tx.setShadowRadius(any(SurfaceControl.class), anyFloat()))
                .thenReturn(tx);
    }
}