diff options
3 files changed, 157 insertions, 10 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index c19a33abf8a4..4855fbd5ba7a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -222,10 +222,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> float shadowRadius = outResult.mDensity * shadowRadiusDp; int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor(); - mTmpColor[0] = Color.red(backgroundColorInt); - mTmpColor[1] = Color.green(backgroundColorInt); - mTmpColor[2] = Color.blue(backgroundColorInt); - t.setCrop(mTaskBackgroundSurface, taskBounds) + mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f; + mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f; + mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f; + t.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height()) .setShadowRadius(mTaskBackgroundSurface, shadowRadius) .setColor(mTaskBackgroundSurface, mTmpColor); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java index 49228720b81d..f8b3fb3def62 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/MockSurfaceControlHelper.java @@ -34,13 +34,12 @@ public class MockSurfaceControlHelper { * given {@link SurfaceControl} when calling {@link SurfaceControl.Builder#build()}. * * @param mockSurfaceControl the first {@link SurfaceControl} to return - * @param mockSurfaceControls following {@link SurfaceControl} to return * @return the mock of {@link SurfaceControl.Builder} */ public static SurfaceControl.Builder createMockSurfaceControlBuilder( - SurfaceControl mockSurfaceControl, SurfaceControl... mockSurfaceControls) { + SurfaceControl mockSurfaceControl) { final SurfaceControl.Builder mockBuilder = mock(SurfaceControl.Builder.class, RETURNS_SELF); - doReturn(mockSurfaceControl, (Object[]) mockSurfaceControls) + doReturn(mockSurfaceControl) .when(mockBuilder) .build(); return mockBuilder; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index 680034bd2ea5..d1b837ef42f1 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -21,23 +21,32 @@ import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceCon import static com.google.common.truth.Truth.assertThat; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.argThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.same; import static org.mockito.Mockito.verify; import android.app.ActivityManager; import android.content.Context; import android.graphics.Color; +import android.graphics.Point; import android.graphics.Rect; import android.testing.AndroidTestingRunner; +import android.util.DisplayMetrics; import android.view.Display; +import android.view.InsetsState; import android.view.SurfaceControl; import android.view.SurfaceControlViewHost; import android.view.View; +import android.view.ViewRootImpl; +import android.view.WindowManager.LayoutParams; import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; @@ -53,6 +62,8 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; +import java.util.ArrayList; +import java.util.List; import java.util.function.Supplier; /** @@ -66,6 +77,8 @@ import java.util.function.Supplier; public class WindowDecorationTests extends ShellTestCase { private static final int CAPTION_HEIGHT_DP = 32; private static final int SHADOW_RADIUS_DP = 5; + private static final Rect TASK_BOUNDS = new Rect(100, 300, 400, 400); + private static final Point TASK_POSITION_IN_PARENT = new Point(40, 60); private final Rect mOutsetsDp = new Rect(); private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult = @@ -84,12 +97,11 @@ public class WindowDecorationTests extends ShellTestCase { @Mock private WindowContainerTransaction mMockWindowContainerTransaction; - private SurfaceControl.Builder mMockSurfaceControlBuilder; + private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>(); private SurfaceControl.Transaction mMockSurfaceControlTransaction; @Before public void setUp() { - mMockSurfaceControlBuilder = createMockSurfaceControlBuilder(mock(SurfaceControl.class)); mMockSurfaceControlTransaction = createMockSurfaceControlTransaction(); doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory) @@ -97,6 +109,128 @@ public class WindowDecorationTests extends ShellTestCase { } @Test + public void testLayoutResultCalculation_invisibleTask() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final SurfaceControl decorContainerSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder decorContainerSurfaceBuilder = + createMockSurfaceControlBuilder(decorContainerSurface); + mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder); + final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder taskBackgroundSurfaceBuilder = + createMockSurfaceControlBuilder(taskBackgroundSurface); + mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder); + + final ActivityManager.TaskDescription.Builder taskDescriptionBuilder = + new ActivityManager.TaskDescription.Builder() + .setBackgroundColor(Color.YELLOW); + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setTaskDescriptionBuilder(taskDescriptionBuilder) + .setBounds(TASK_BOUNDS) + .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y) + .setVisible(false) + .build(); + taskInfo.isFocused = false; + // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is + // 64px. + taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; + mOutsetsDp.set(10, 20, 30, 40); + + final SurfaceControl taskSurface = mock(SurfaceControl.class); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); + + windowDecor.relayout(taskInfo); + + verify(decorContainerSurfaceBuilder, never()).build(); + verify(taskBackgroundSurfaceBuilder, never()).build(); + verify(mMockSurfaceControlViewHostFactory, never()) + .create(any(), any(), any(), anyBoolean()); + + verify(mMockSurfaceControlTransaction).hide(taskSurface); + + assertNull(mRelayoutResult.mRootView); + } + + @Test + public void testLayoutResultCalculation_visibleFocusedTask() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final SurfaceControl decorContainerSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder decorContainerSurfaceBuilder = + createMockSurfaceControlBuilder(decorContainerSurface); + mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder); + final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder taskBackgroundSurfaceBuilder = + createMockSurfaceControlBuilder(taskBackgroundSurface); + mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder); + + final ActivityManager.TaskDescription.Builder taskDescriptionBuilder = + new ActivityManager.TaskDescription.Builder() + .setBackgroundColor(Color.YELLOW); + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setTaskDescriptionBuilder(taskDescriptionBuilder) + .setBounds(TASK_BOUNDS) + .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y) + .setVisible(true) + .build(); + taskInfo.isFocused = true; + // Density is 2. Outsets are (20, 40, 60, 80) px. Shadow radius is 10px. Caption height is + // 64px. + taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; + mOutsetsDp.set(10, 20, 30, 40); + + final SurfaceControl taskSurface = mock(SurfaceControl.class); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); + + windowDecor.relayout(taskInfo); + + verify(decorContainerSurfaceBuilder).setParent(taskSurface); + verify(decorContainerSurfaceBuilder).setContainerLayer(); + verify(mMockSurfaceControlTransaction).setTrustedOverlay(decorContainerSurface, true); + verify(mMockSurfaceControlTransaction).setPosition(decorContainerSurface, -20, -40); + verify(mMockSurfaceControlTransaction).setWindowCrop(decorContainerSurface, 380, 220); + + verify(taskBackgroundSurfaceBuilder).setParent(taskSurface); + verify(taskBackgroundSurfaceBuilder).setEffectLayer(); + verify(mMockSurfaceControlTransaction).setWindowCrop(taskBackgroundSurface, 300, 100); + verify(mMockSurfaceControlTransaction) + .setColor(taskBackgroundSurface, new float[] {1.f, 1.f, 0.f}); + verify(mMockSurfaceControlTransaction).setShadowRadius(taskBackgroundSurface, 10); + + verify(mMockSurfaceControlViewHostFactory) + .create(any(), eq(defaultDisplay), any(), anyBoolean()); + verify(mMockSurfaceControlViewHost) + .setView(same(mMockView), + argThat(lp -> lp.height == 64 + && lp.width == 300 + && (lp.flags & LayoutParams.FLAG_NOT_FOCUSABLE) != 0)); + if (ViewRootImpl.CAPTION_ON_SHELL) { + verify(mMockView).setTaskFocusState(true); + verify(mMockWindowContainerTransaction) + .addRectInsetsProvider(taskInfo.token, + new Rect(100, 300, 400, 364), + new int[] { InsetsState.ITYPE_CAPTION_BAR }); + } + + verify(mMockSurfaceControlTransaction) + .setPosition(taskSurface, TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y); + verify(mMockSurfaceControlTransaction) + .setCrop(taskSurface, new Rect(-20, -40, 360, 180)); + verify(mMockSurfaceControlTransaction) + .show(taskSurface); + + assertEquals(380, mRelayoutResult.mWidth); + assertEquals(220, mRelayoutResult.mHeight); + assertEquals(2, mRelayoutResult.mDensity, 0.f); + } + + @Test public void testNotCrashWhenDisplayAppearsAfterTask() { doReturn(mock(Display.class)).when(mMockDisplayController) .getDisplay(Display.DEFAULT_DISPLAY); @@ -145,10 +279,24 @@ public class WindowDecorationTests extends ShellTestCase { private TestWindowDecoration createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) { return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer, - taskInfo, testSurface, () -> mMockSurfaceControlBuilder, + taskInfo, testSurface, new MockSurfaceControlBuilderSupplier(), mMockSurfaceControlViewHostFactory); } + private class MockSurfaceControlBuilderSupplier implements Supplier<SurfaceControl.Builder> { + private int mNumOfCalls = 0; + + @Override + public SurfaceControl.Builder get() { + final SurfaceControl.Builder builder = + mNumOfCalls < mMockSurfaceControlBuilders.size() + ? mMockSurfaceControlBuilders.get(mNumOfCalls) + : createMockSurfaceControlBuilder(mock(SurfaceControl.class)); + ++mNumOfCalls; + return builder; + } + } + private static class TestView extends View implements TaskFocusStateConsumer { private TestView(Context context) { super(context); |