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

Commit e3cb1c25 authored by Massimo Carli's avatar Massimo Carli
Browse files

[26/n] Adding tests to AppCompatReachability* classes

Flag: EXEMPT refactor
Bug: 336807329
Test: atest WmTests:AppCompatReachabilityPolicyTest
Test: atest WmTests:AppCompatReachabilityOverridesTest

Change-Id: I88a589f36631ea9244580ec6f9488ba21d5a5473
parent 805eff4e
Loading
Loading
Loading
Loading
+0 −3
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.annotation.NonNull;
import android.content.res.Configuration;
import android.graphics.Rect;

import com.android.internal.annotations.VisibleForTesting;
import com.android.window.flags.Flags;

/**
@@ -112,12 +111,10 @@ class AppCompatReachabilityOverrides {
                : mAppCompatConfiguration.getLetterboxVerticalPositionMultiplier(tabletopMode);
    }

    @VisibleForTesting
    boolean isHorizontalReachabilityEnabled() {
        return isHorizontalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
    }

    @VisibleForTesting
    boolean isVerticalReachabilityEnabled() {
        return isVerticalReachabilityEnabled(mActivityRecord.getParent().getConfiguration());
    }
+4 −1
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Rect;

import com.android.internal.annotations.VisibleForTesting;

import java.util.function.Supplier;

/**
@@ -43,7 +45,8 @@ class AppCompatReachabilityPolicy {
    @NonNull
    private final AppCompatConfiguration mAppCompatConfiguration;
    @Nullable
    private Supplier<Rect> mLetterboxInnerBoundsSupplier;
    @VisibleForTesting
    Supplier<Rect> mLetterboxInnerBoundsSupplier;

    AppCompatReachabilityPolicy(@NonNull ActivityRecord activityRecord,
            @NonNull AppCompatConfiguration appCompatConfiguration) {
+59 −8
Original line number Diff line number Diff line
@@ -36,9 +36,12 @@ import android.content.ComponentName;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.view.Surface;

import androidx.annotation.CallSuper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import com.android.server.wm.utils.TestComponentStack;

@@ -74,6 +77,9 @@ class AppCompatActivityRobot {
    private final int mDisplayHeight;
    private DisplayContent mDisplayContent;

    @Nullable
    private Consumer<ActivityRecord> mOnPostActivityCreation;

    AppCompatActivityRobot(@NonNull WindowManagerService wm,
            @NonNull ActivityTaskManagerService atm, @NonNull ActivityTaskSupervisor supervisor,
            int displayWidth, int displayHeight) {
@@ -96,6 +102,10 @@ class AppCompatActivityRobot {
                /* inNewDisplay */ false);
    }

    void createActivityWithComponentWithoutTask() {
        createActivityWithComponentInNewTask(/* inNewTask */ false, /* inNewDisplay */ false);
    }

    void createActivityWithComponentInNewTask() {
        createActivityWithComponentInNewTask(/* inNewTask */ true, /* inNewDisplay */ false);
    }
@@ -130,6 +140,14 @@ class AppCompatActivityRobot {
        doReturn(naturalOrientation).when(mDisplayContent).getNaturalOrientation();
    }

    void configureTaskBounds(@NonNull Rect taskBounds) {
        doReturn(taskBounds).when(mTaskStack.top()).getBounds();
    }

    void configureTopActivityBounds(@NonNull Rect activityBounds) {
        doReturn(activityBounds).when(mActivityStack.top()).getBounds();
    }

    @NonNull
    ActivityRecord top() {
        return mActivityStack.top();
@@ -169,6 +187,10 @@ class AppCompatActivityRobot {
                .isActivityEligibleForOrientationOverride(eq(mActivityStack.top()));
    }

    void setTopActivityInTransition(boolean inTransition) {
        doReturn(inTransition).when(mActivityStack.top()).isInTransition();
    }

    void setShouldApplyUserMinAspectRatioOverride(boolean enabled) {
        doReturn(enabled).when(mActivityStack.top().mAppCompatController
                .getAppCompatAspectRatioOverrides()).shouldApplyUserMinAspectRatioOverride();
@@ -378,6 +400,32 @@ class AppCompatActivityRobot {
        pushActivity(newActivity);
    }

    /**
     * Specific Robots can override this method to add operation to run on a newly created
     * {@link ActivityRecord}. Common case is to invoke spyOn().
     *
     * @param activity The newly created {@link ActivityRecord}.
     */
    @CallSuper
    void onPostActivityCreation(@NonNull ActivityRecord activity) {
        spyOn(activity);
        spyOn(activity.mLetterboxUiController);
        if (mOnPostActivityCreation != null) {
            mOnPostActivityCreation.accept(activity);
        }
    }

    /**
     * Each Robot can specify its own set of operation to execute on a newly created
     * {@link ActivityRecord}. Most common the use of spyOn().
     *
     * @param onPostActivityCreation The reference to the code to execute after the creation of a
     *                               new {@link ActivityRecord}.
     */
    void setOnPostActivityCreation(@Nullable Consumer<ActivityRecord> onPostActivityCreation) {
        mOnPostActivityCreation = onPostActivityCreation;
    }

    private void createActivityWithComponentInNewTask(boolean inNewTask, boolean inNewDisplay) {
        if (inNewDisplay) {
            createNewDisplay();
@@ -385,14 +433,16 @@ class AppCompatActivityRobot {
        if (inNewTask) {
            createNewTask();
        }
        final ActivityRecord activity = new WindowTestsBase.ActivityBuilder(mAtm)
                .setOnTop(true)
                .setTask(mTaskStack.top())
        final WindowTestsBase.ActivityBuilder activityBuilder =
                new WindowTestsBase.ActivityBuilder(mAtm).setOnTop(true)
                // Set the component to be that of the test class in order
                // to enable compat changes
                .setComponent(ComponentName.createRelative(mAtm.mContext, TEST_COMPONENT_NAME))
                .build();
        pushActivity(activity);
                .setComponent(ComponentName.createRelative(mAtm.mContext, TEST_COMPONENT_NAME));
        if (!mTaskStack.isEmpty()) {
            // We put the Activity in the current task if any.
            activityBuilder.setTask(mTaskStack.top());
        }
        pushActivity(activityBuilder.build());
    }

    /**
@@ -438,14 +488,15 @@ class AppCompatActivityRobot {
    // We add the activity to the stack and spyOn() on its properties.
    private void pushActivity(@NonNull ActivityRecord activity) {
        mActivityStack.push(activity);
        spyOn(activity);
        onPostActivityCreation(activity);
        // TODO (b/351763164): Use these spyOn calls only when necessary.
        spyOn(activity.mAppCompatController.getTransparentPolicy());
        spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides());
        spyOn(activity.mAppCompatController.getAppCompatAspectRatioPolicy());
        spyOn(activity.mAppCompatController.getAppCompatFocusOverrides());
        spyOn(activity.mAppCompatController.getAppCompatResizeOverrides());
        spyOn(activity.mLetterboxUiController);
        spyOn(activity.mAppCompatController.getAppCompatReachabilityPolicy());
        spyOn(activity.mAppCompatController.getAppCompatReachabilityOverrides());
    }

    private void pushTask(@NonNull Task task) {
+33 −0
Original line number Diff line number Diff line
@@ -19,6 +19,9 @@ package com.android.server.wm;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import androidx.annotation.NonNull;
@@ -80,4 +83,34 @@ class AppCompatConfigurationRobot {
        doReturn(aspectRatio).when(mAppCompatConfiguration)
                .getFixedOrientationLetterboxAspectRatio();
    }

    void setThinLetterboxWidthPx(int thinWidthPx) {
        doReturn(thinWidthPx).when(mAppCompatConfiguration)
                .getThinLetterboxWidthPx();
    }

    void setThinLetterboxHeightPx(int thinHeightPx) {
        doReturn(thinHeightPx).when(mAppCompatConfiguration)
                .getThinLetterboxHeightPx();
    }

    void checkToNextLeftStop(boolean invoked) {
        verify(mAppCompatConfiguration, times(invoked ? 1 : 0))
                .movePositionForHorizontalReachabilityToNextLeftStop(anyBoolean());
    }

    void checkToNextRightStop(boolean invoked) {
        verify(mAppCompatConfiguration, times(invoked ? 1 : 0))
                .movePositionForHorizontalReachabilityToNextRightStop(anyBoolean());
    }

    void checkToNextBottomStop(boolean invoked) {
        verify(mAppCompatConfiguration, times(invoked ? 1 : 0))
                .movePositionForVerticalReachabilityToNextBottomStop(anyBoolean());
    }

    void checkToNextTopStop(boolean invoked) {
        verify(mAppCompatConfiguration, times(invoked ? 1 : 0))
                .movePositionForVerticalReachabilityToNextTopStop(anyBoolean());
    }
}
+227 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server.wm;

import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;

import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;

import android.compat.testing.PlatformCompatChangeRule;
import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;

import androidx.annotation.NonNull;

import com.android.window.flags.Flags;

import junit.framework.Assert;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;

import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Test class for {@link AppCompatReachabilityOverrides}.
 * <p>
 * Build/Install/Run:
 * atest WmTests:AppCompatReachabilityOverridesTest
 */
@Presubmit
@RunWith(WindowTestRunner.class)
public class AppCompatReachabilityOverridesTest extends WindowTestsBase {

    @Rule
    public TestRule compatChangeRule = new PlatformCompatChangeRule();

    @Test
    public void testIsThinLetterboxed_NegativePx_returnsFalse() {
        runTestScenario((robot) -> {
            robot.activity().createActivityWithComponentWithoutTask();
            robot.conf().setThinLetterboxHeightPx(/* thinHeightPx */ -1);
            robot.checkIsVerticalThinLetterboxed(/* expected */ false);

            robot.conf().setThinLetterboxWidthPx(/* thinHeightPx */ -1);
            robot.checkIsHorizontalThinLetterboxed(/* expected */ false);
        });
    }

    @Test
    public void testIsThinLetterboxed_noTask_returnsFalse() {
        runTestScenario((robot) -> {
            robot.activity().createActivityWithComponentWithoutTask();
            robot.conf().setThinLetterboxHeightPx(/* thinHeightPx */ 10);
            robot.checkIsVerticalThinLetterboxed(/* expected */ false);

            robot.conf().setThinLetterboxWidthPx(/* thinHeightPx */ 10);
            robot.checkIsHorizontalThinLetterboxed(/* expected */ false);
        });
    }

    @Test
    public void testIsVerticalThinLetterboxed() {
        runTestScenario((robot) -> {
            robot.conf().setThinLetterboxHeightPx(/* thinHeightPx */ 10);
            robot.applyOnActivity((a) -> {
                a.createActivityWithComponent();
                a.configureTaskBounds(new Rect(0, 0, 100, 100));

                // (task.width() - act.width()) / 2  = 5 < 10
                a.configureTopActivityBounds(new Rect(5, 5, 95, 95));
                robot.checkIsVerticalThinLetterboxed(/* expected */ true);

                // (task.width() - act.width()) / 2  = 10 = 10
                a.configureTopActivityBounds(new Rect(10, 10, 90, 90));
                robot.checkIsVerticalThinLetterboxed(/* expected */ true);

                // (task.width() - act.width()) / 2  = 11 > 10
                a.configureTopActivityBounds(new Rect(11, 11, 89, 89));
                robot.checkIsVerticalThinLetterboxed(/* expected */ false);
            });
        });
    }

    @Test
    public void testIsHorizontalThinLetterboxed() {
        runTestScenario((robot) -> {
            robot.conf().setThinLetterboxWidthPx(/* thinHeightPx */ 10);
            robot.applyOnActivity((a) -> {
                a.createActivityWithComponent();
                a.configureTaskBounds(new Rect(0, 0, 100, 100));

                // (task.height() - act.height()) / 2  = 5 < 10
                a.configureTopActivityBounds(new Rect(5, 5, 95, 95));
                robot.checkIsHorizontalThinLetterboxed(/* expected */ true);

                // (task.height() - act.height()) / 2  = 10 = 10
                a.configureTopActivityBounds(new Rect(10, 10, 90, 90));
                robot.checkIsHorizontalThinLetterboxed(/* expected */ true);

                // (task.height() - act.height()) / 2  = 11 > 10
                a.configureTopActivityBounds(new Rect(11, 11, 89, 89));
                robot.checkIsHorizontalThinLetterboxed(/* expected */ false);
            });
        });
    }

    @Test
    @EnableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
    public void testAllowReachabilityForThinLetterboxWithFlagEnabled() {
        runTestScenario((robot) -> {
            robot.activity().createActivityWithComponent();

            robot.configureIsVerticalThinLetterboxed(/* isThin */ true);
            robot.checkAllowVerticalReachabilityForThinLetterbox(/* expected */ false);
            robot.configureIsHorizontalThinLetterboxed(/* isThin */ true);
            robot.checkAllowHorizontalReachabilityForThinLetterbox(/* expected */ false);

            robot.configureIsVerticalThinLetterboxed(/* isThin */ false);
            robot.checkAllowVerticalReachabilityForThinLetterbox(/* expected */ true);
            robot.configureIsHorizontalThinLetterboxed(/* isThin */ false);
            robot.checkAllowHorizontalReachabilityForThinLetterbox(/* expected */ true);
        });
    }

    @Test
    @DisableFlags(Flags.FLAG_DISABLE_THIN_LETTERBOXING_POLICY)
    public void testAllowReachabilityForThinLetterboxWithFlagDisabled() {
        runTestScenario((robot) -> {
            robot.activity().createActivityWithComponent();

            robot.configureIsVerticalThinLetterboxed(/* isThin */ true);
            robot.checkAllowVerticalReachabilityForThinLetterbox(/* expected */ true);
            robot.configureIsHorizontalThinLetterboxed(/* isThin */ true);
            robot.checkAllowHorizontalReachabilityForThinLetterbox(/* expected */ true);

            robot.configureIsVerticalThinLetterboxed(/* isThin */ false);
            robot.checkAllowVerticalReachabilityForThinLetterbox(/* expected */ true);
            robot.configureIsHorizontalThinLetterboxed(/* isThin */ false);
            robot.checkAllowHorizontalReachabilityForThinLetterbox(/* expected */ true);
        });
    }

    /**
     * Runs a test scenario providing a Robot.
     */
    void runTestScenario(@NonNull Consumer<ReachabilityOverridesRobotTest> consumer) {
        spyOn(mWm.mAppCompatConfiguration);
        final ReachabilityOverridesRobotTest robot =
                new ReachabilityOverridesRobotTest(mWm, mAtm, mSupervisor);
        consumer.accept(robot);
    }

    private static class ReachabilityOverridesRobotTest extends AppCompatRobotBase {

        private final Supplier<Rect> mLetterboxInnerBoundsSupplier = spy(Rect::new);

        ReachabilityOverridesRobotTest(@NonNull WindowManagerService wm,
                @NonNull ActivityTaskManagerService atm,
                @NonNull ActivityTaskSupervisor supervisor) {
            super(wm, atm, supervisor);
        }

        @Override
        void onPostActivityCreation(@NonNull ActivityRecord activity) {
            super.onPostActivityCreation(activity);
            activity.mAppCompatController.getAppCompatReachabilityPolicy()
                    .setLetterboxInnerBoundsSupplier(mLetterboxInnerBoundsSupplier);
        }

        void configureIsVerticalThinLetterboxed(boolean isThin) {
            doReturn(isThin).when(getAppCompatReachabilityOverrides())
                    .isVerticalThinLetterboxed();
        }

        void configureIsHorizontalThinLetterboxed(boolean isThin) {
            doReturn(isThin).when(getAppCompatReachabilityOverrides())
                    .isHorizontalThinLetterboxed();
        }

        void checkIsVerticalThinLetterboxed(boolean expected) {
            Assert.assertEquals(expected,
                    getAppCompatReachabilityOverrides().isVerticalThinLetterboxed());
        }

        void checkIsHorizontalThinLetterboxed(boolean expected) {
            Assert.assertEquals(expected,
                    getAppCompatReachabilityOverrides().isHorizontalThinLetterboxed());
        }

        void checkAllowVerticalReachabilityForThinLetterbox(boolean expected) {
            Assert.assertEquals(expected, getAppCompatReachabilityOverrides()
                    .allowVerticalReachabilityForThinLetterbox());
        }

        void checkAllowHorizontalReachabilityForThinLetterbox(boolean expected) {
            Assert.assertEquals(expected, getAppCompatReachabilityOverrides()
                    .allowHorizontalReachabilityForThinLetterbox());
        }

        @NonNull
        private AppCompatReachabilityOverrides getAppCompatReachabilityOverrides() {
            return activity().top().mAppCompatController.getAppCompatReachabilityOverrides();
        }

    }

}
Loading