Merge "Add unit tests for layout of window decoration" into tm-qpr-dev

This commit is contained in:
TreeHugger Robot
2022-07-27 04:30:41 +00:00
committed by Android (Google) Code Review
3 changed files with 157 additions and 10 deletions

View File

@@ -222,10 +222,10 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
float shadowRadius = outResult.mDensity * shadowRadiusDp; float shadowRadius = outResult.mDensity * shadowRadiusDp;
int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor(); int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor();
mTmpColor[0] = Color.red(backgroundColorInt); mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
mTmpColor[1] = Color.green(backgroundColorInt); mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
mTmpColor[2] = Color.blue(backgroundColorInt); mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
t.setCrop(mTaskBackgroundSurface, taskBounds) t.setWindowCrop(mTaskBackgroundSurface, taskBounds.width(), taskBounds.height())
.setShadowRadius(mTaskBackgroundSurface, shadowRadius) .setShadowRadius(mTaskBackgroundSurface, shadowRadius)
.setColor(mTaskBackgroundSurface, mTmpColor); .setColor(mTaskBackgroundSurface, mTmpColor);

View File

@@ -34,13 +34,12 @@ public class MockSurfaceControlHelper {
* given {@link SurfaceControl} when calling {@link SurfaceControl.Builder#build()}. * given {@link SurfaceControl} when calling {@link SurfaceControl.Builder#build()}.
* *
* @param mockSurfaceControl the first {@link SurfaceControl} to return * @param mockSurfaceControl the first {@link SurfaceControl} to return
* @param mockSurfaceControls following {@link SurfaceControl} to return
* @return the mock of {@link SurfaceControl.Builder} * @return the mock of {@link SurfaceControl.Builder}
*/ */
public static SurfaceControl.Builder createMockSurfaceControlBuilder( public static SurfaceControl.Builder createMockSurfaceControlBuilder(
SurfaceControl mockSurfaceControl, SurfaceControl... mockSurfaceControls) { SurfaceControl mockSurfaceControl) {
final SurfaceControl.Builder mockBuilder = mock(SurfaceControl.Builder.class, RETURNS_SELF); final SurfaceControl.Builder mockBuilder = mock(SurfaceControl.Builder.class, RETURNS_SELF);
doReturn(mockSurfaceControl, (Object[]) mockSurfaceControls) doReturn(mockSurfaceControl)
.when(mockBuilder) .when(mockBuilder)
.build(); .build();
return mockBuilder; return mockBuilder;

View File

@@ -21,23 +21,32 @@ import static com.android.wm.shell.MockSurfaceControlHelper.createMockSurfaceCon
import static com.google.common.truth.Truth.assertThat; 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.any;
import static org.mockito.Mockito.anyBoolean; import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq; import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.same; import static org.mockito.Mockito.same;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.app.ActivityManager; import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.testing.AndroidTestingRunner; import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
import android.view.Display; import android.view.Display;
import android.view.InsetsState;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost; import android.view.SurfaceControlViewHost;
import android.view.View; import android.view.View;
import android.view.ViewRootImpl;
import android.view.WindowManager.LayoutParams;
import android.window.WindowContainerTransaction; import android.window.WindowContainerTransaction;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -53,6 +62,8 @@ import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
import org.mockito.Mock; import org.mockito.Mock;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@@ -66,6 +77,8 @@ import java.util.function.Supplier;
public class WindowDecorationTests extends ShellTestCase { public class WindowDecorationTests extends ShellTestCase {
private static final int CAPTION_HEIGHT_DP = 32; private static final int CAPTION_HEIGHT_DP = 32;
private static final int SHADOW_RADIUS_DP = 5; 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 Rect mOutsetsDp = new Rect();
private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult = private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult =
@@ -84,18 +97,139 @@ public class WindowDecorationTests extends ShellTestCase {
@Mock @Mock
private WindowContainerTransaction mMockWindowContainerTransaction; private WindowContainerTransaction mMockWindowContainerTransaction;
private SurfaceControl.Builder mMockSurfaceControlBuilder; private final List<SurfaceControl.Builder> mMockSurfaceControlBuilders = new ArrayList<>();
private SurfaceControl.Transaction mMockSurfaceControlTransaction; private SurfaceControl.Transaction mMockSurfaceControlTransaction;
@Before @Before
public void setUp() { public void setUp() {
mMockSurfaceControlBuilder = createMockSurfaceControlBuilder(mock(SurfaceControl.class));
mMockSurfaceControlTransaction = createMockSurfaceControlTransaction(); mMockSurfaceControlTransaction = createMockSurfaceControlTransaction();
doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory) doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory)
.create(any(), any(), any(), anyBoolean()); .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 @Test
public void testNotCrashWhenDisplayAppearsAfterTask() { public void testNotCrashWhenDisplayAppearsAfterTask() {
doReturn(mock(Display.class)).when(mMockDisplayController) doReturn(mock(Display.class)).when(mMockDisplayController)
@@ -145,10 +279,24 @@ public class WindowDecorationTests extends ShellTestCase {
private TestWindowDecoration createWindowDecoration( private TestWindowDecoration createWindowDecoration(
ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) { ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer, return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
taskInfo, testSurface, () -> mMockSurfaceControlBuilder, taskInfo, testSurface, new MockSurfaceControlBuilderSupplier(),
mMockSurfaceControlViewHostFactory); 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 static class TestView extends View implements TaskFocusStateConsumer {
private TestView(Context context) { private TestView(Context context) {
super(context); super(context);