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

Commit e4916371 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

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

parents b7ca84c0 55544c88
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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);

+2 −3
Original line number Diff line number Diff line
@@ -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;
+151 −3
Original line number Diff line number Diff line
@@ -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);