Add unit tests for layout of window decoration
This also fixes a few bugs discovered by this unit test. Bug: 240202224 Test: atest WindowDecorationTest with caption on shell enabled. Change-Id: I60f75b460e2349666acbd839ba8f81fc9c96d7b6
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,18 +97,139 @@ 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)
|
||||
.create(any(), any(), any(), anyBoolean());
|
||||
}
|
||||
|
||||
@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)
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user