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

Commit 5575f8f2 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add box shadows to PiP 2" into main

parents fc45b428 4369d0ba
Loading
Loading
Loading
Loading
+46 −1
Original line number Diff line number Diff line
@@ -19,10 +19,15 @@ package com.android.wm.shell.pip2;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.gui.BorderSettings;
import android.gui.BoxShadowSettings;
import android.view.Choreographer;
import android.view.SurfaceControl;

import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.common.BoxShadowHelper;
import com.android.wm.shell.common.pip.PipUtils;

/**
 * Abstracts the common operations on {@link SurfaceControl.Transaction} for PiP transition.
@@ -36,12 +41,42 @@ public class PipSurfaceTransactionHelper {
    private final int mShadowRadius;
    private final float mMirrorOpacity;

    private BoxShadowSettings mBoxShadowSettings;
    private BorderSettings mBorderSettings;

    public PipSurfaceTransactionHelper(Context context) {
        mCornerRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_corner_radius);
        mShadowRadius = context.getResources().getDimensionPixelSize(R.dimen.pip_shadow_radius);
        mMirrorOpacity = context.getResources().getFloat(
                R.dimen.config_pipDraggingAcrossDisplaysOpacity);
        onThemeChanged(context);
    }

    /**
     * Called when theme changes.
     *
     * @param context the current context
     */
    public void onThemeChanged(Context context) {
        if (Flags.enablePipBoxShadows()) {
            if (PipUtils.isDarkSystemTheme(context)) {
                mBoxShadowSettings = BoxShadowHelper.getBoxShadowSettings(context,
                        new int[]{R.style.BoxShadowParamsPIPDark1,
                                R.style.BoxShadowParamsPIPDark2});
                mBorderSettings = BoxShadowHelper.getBorderSettings(context,
                        R.style.BorderSettingsPIPDark);
            } else {
                mBoxShadowSettings = BoxShadowHelper.getBoxShadowSettings(context,
                        new int[]{R.style.BoxShadowParamsPIPLight1,
                                R.style.BoxShadowParamsPIPLight2});

                mBorderSettings = BoxShadowHelper.getBorderSettings(context,
                        R.style.BorderSettingsPIPLight);
            }
        }
    }



    /**
     * Gets corner radius which is loaded from resources.
@@ -162,7 +197,17 @@ public class PipSurfaceTransactionHelper {
     */
    public PipSurfaceTransactionHelper shadow(SurfaceControl.Transaction tx, SurfaceControl leash,
            boolean applyShadowRadius) {
        if (Flags.enablePipBoxShadows()) {
            if (applyShadowRadius) {
                tx.setBoxShadowSettings(leash, mBoxShadowSettings);
                tx.setBorderSettings(leash, mBorderSettings);
            } else {
                tx.setBoxShadowSettings(leash, new BoxShadowSettings());
                tx.setBorderSettings(leash, new BorderSettings());
            }
        } else {
            tx.setShadowRadius(leash, applyShadowRadius ? mShadowRadius : 0);
        }
        return this;
    }

+14 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.Preconditions;
import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayChangeController;
@@ -122,6 +123,8 @@ public class PipController implements ConfigurationChangeListener,
    // Wrapper for making Binder calls into PiP animation listener hosted in launcher's Recents.
    @Nullable private PipAnimationListener mPipRecentsAnimationListener;

    private final PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
            mSurfaceControlTransactionFactory;
    private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;

    private boolean mWaitingToPlayDisplayChangeBoundsUpdate;
@@ -193,6 +196,8 @@ public class PipController implements ConfigurationChangeListener,
        mPipSurfaceTransactionHelper = pipSurfaceTransactionHelper;
        mMainExecutor = mainExecutor;
        mImpl = new PipImpl();
        mSurfaceControlTransactionFactory =
                new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory();

        if (PipUtils.isPip2ExperimentEnabled()) {
            shellInit.addInitCallback(this::onInit, this);
@@ -370,6 +375,15 @@ public class PipController implements ConfigurationChangeListener,
    @Override
    public void onThemeChanged() {
        setDisplayLayout(new DisplayLayout(mContext, mContext.getDisplay()));
        if (Flags.enablePipBoxShadows()) {
            if (mPipTransitionState.isInPip()) {
                SurfaceControl pipLeash = mPipTransitionState.getPinnedTaskLeash();
                mPipSurfaceTransactionHelper.onThemeChanged(mContext);
                SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
                mPipSurfaceTransactionHelper.shadow(tx, pipLeash, true /* applyShadowRadius */);
                tx.apply();
            }
        }
    }

    //
+108 −1
Original line number Diff line number Diff line
@@ -16,25 +16,38 @@

package com.android.wm.shell.pip2;

import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyFloat;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.Context;
import android.content.res.Resources;
import android.gui.BorderSettings;
import android.gui.BoxShadowSettings;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.SurfaceControl;

import androidx.test.filters.SmallTest;

import com.android.modules.utils.testing.ExtendedMockitoRule;
import com.android.wm.shell.Flags;
import com.android.wm.shell.R;
import com.android.wm.shell.common.BoxShadowHelper;
import com.android.wm.shell.common.pip.PipUtils;

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

@@ -50,13 +63,34 @@ public class PipSurfaceTransactionHelperTest {
    private static final int SHADOW_RADIUS = 20;
    private static final float MIRROR_OPACITY = 0.5f;

    private final BoxShadowSettings mLightBoxShadowSettings = new BoxShadowSettings();
    private final BorderSettings mLightBorderSettings = new BorderSettings();
    private final BoxShadowSettings mDarkBoxShadowSettings = new BoxShadowSettings();
    private final BorderSettings mDarkBorderSettings = new BorderSettings();

    private static final int[] LIGHT_SHADOW_STYLES = {
            R.style.BoxShadowParamsPIPLight1, R.style.BoxShadowParamsPIPLight2};
    private static final int[] DARK_SHADOW_STYLES = {
            R.style.BoxShadowParamsPIPDark1, R.style.BoxShadowParamsPIPDark2};
    private static final int LIGHT_BORDER_STYLE = R.style.BorderSettingsPIPLight;
    private static final int DARK_BORDER_STYLE = R.style.BorderSettingsPIPDark;

    @Mock private Context mMockContext;
    @Mock private Resources mMockResources;
    @Mock private SurfaceControl.Transaction mMockTransaction;

    private PipSurfaceTransactionHelper mPipSurfaceTransactionHelper;
    private SurfaceControl mTestLeash;


    @Rule
    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    @Rule
    public final ExtendedMockitoRule mExtendedMockitoRule = new ExtendedMockitoRule.Builder(this)
            .mockStatic(BoxShadowHelper.class)
            .mockStatic(PipUtils.class)
            .build();

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
@@ -78,6 +112,30 @@ public class PipSurfaceTransactionHelperTest {
                .setName("PipSurfaceTransactionHelperTest")
                .setCallsite("PipSurfaceTransactionHelperTest")
                .build();

        when(mMockTransaction.setCornerRadius(any(SurfaceControl.class), anyFloat()))
                .thenReturn(mMockTransaction);
        when(mMockTransaction.setShadowRadius(any(SurfaceControl.class), anyFloat()))
                .thenReturn(mMockTransaction);
        when(mMockTransaction.setBoxShadowSettings(any(SurfaceControl.class),
                any(BoxShadowSettings.class)))
                .thenReturn(mMockTransaction);
        when(mMockTransaction.setBorderSettings(any(SurfaceControl.class),
                any(BorderSettings.class)))
                .thenReturn(mMockTransaction);

        when(BoxShadowHelper.getBoxShadowSettings(
                eq(mMockContext), aryEq(LIGHT_SHADOW_STYLES))).thenReturn(
                mLightBoxShadowSettings);
        when(BoxShadowHelper.getBorderSettings(
                eq(mMockContext), eq(LIGHT_BORDER_STYLE))).thenReturn(mLightBorderSettings);

        when(BoxShadowHelper.getBoxShadowSettings(
                eq(mMockContext), aryEq(DARK_SHADOW_STYLES))).thenReturn(mDarkBoxShadowSettings);
        when(BoxShadowHelper.getBorderSettings(
                eq(mMockContext), eq(DARK_BORDER_STYLE))).thenReturn(mDarkBorderSettings);


    }

    @Test
@@ -108,6 +166,55 @@ public class PipSurfaceTransactionHelperTest {
        verify(mMockTransaction).setShadowRadius(eq(mTestLeash), eq((float) SHADOW_RADIUS));
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_PIP_BOX_SHADOWS)
    public void shadow_flagEnabled_applyFalse_setsEmptyBoxShadowAndBorder() {
        mPipSurfaceTransactionHelper.shadow(mMockTransaction, mTestLeash, false /* apply */);

        ArgumentCaptor<BoxShadowSettings> boxShadow = ArgumentCaptor.forClass(
                BoxShadowSettings.class);
        ArgumentCaptor<BorderSettings> border = ArgumentCaptor.forClass(BorderSettings.class);

        verify(mMockTransaction).setBoxShadowSettings(eq(mTestLeash), boxShadow.capture());
        verify(mMockTransaction).setBorderSettings(eq(mTestLeash), border.capture());
        verify(mMockTransaction, never()).setShadowRadius(any(), anyFloat());

        assertEquals(0, boxShadow.getValue().boxShadows.length);
        assertEquals(0, border.getValue().strokeWidth, 0.0);
        assertEquals(0, border.getValue().color);
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_PIP_BOX_SHADOWS)
    public void onThemeChanged_switchToDarkTheme_usesDarkSettingsOnShadow() {
        when(PipUtils.isDarkSystemTheme(mMockContext)).thenReturn(true);

        mPipSurfaceTransactionHelper.onThemeChanged(mMockContext);

        mPipSurfaceTransactionHelper.shadow(mMockTransaction, mTestLeash, true /* apply */);

        verify(mMockTransaction).setBoxShadowSettings(eq(mTestLeash),
                eq(mDarkBoxShadowSettings));
        verify(mMockTransaction).setBorderSettings(eq(mTestLeash), eq(mDarkBorderSettings));
        verify(mMockTransaction, never()).setShadowRadius(any(), anyFloat());
    }


    @Test
    @EnableFlags(Flags.FLAG_ENABLE_PIP_BOX_SHADOWS)
    public void onThemeChanged_switchToLightTheme_usesLightSettingsOnShadow() {
        when(PipUtils.isDarkSystemTheme(mMockContext)).thenReturn(false);

        mPipSurfaceTransactionHelper.onThemeChanged(mMockContext);

        mPipSurfaceTransactionHelper.shadow(mMockTransaction, mTestLeash, true /* apply */);

        verify(mMockTransaction).setBoxShadowSettings(eq(mTestLeash),
                eq(mLightBoxShadowSettings));
        verify(mMockTransaction).setBorderSettings(eq(mTestLeash), eq(mLightBorderSettings));
        verify(mMockTransaction, never()).setShadowRadius(any(), anyFloat());
    }

    @Test
    public void setMirrorTransformations_setsAlphaAndLayer() {
        mPipSurfaceTransactionHelper.setMirrorTransformations(mMockTransaction, mTestLeash);