diff options
| author | 2024-06-11 07:56:22 +0000 | |
|---|---|---|
| committer | 2024-06-19 17:24:57 +0000 | |
| commit | 49c49da23e5362dee2df1cfc4ccd62bb5bf46dab (patch) | |
| tree | b30cbcdb0dfa3ddc5205b3a70092f11a940b92d2 | |
| parent | 0ae69b634351517e343d24929e250ee99a1ff7a3 (diff) | |
[8/n] AppCompatOrientationCapabilityTest implementation
Migration of the test about orientation in app compat
to AppCompatOrientationCapabilityTest from
LetterboxUiController
Flag: EXEMPT refactor
Bug: 346264992
Fix: 348108719
Test: atest WmTests:AppCompatOrientationCapabilityTest
Test: atest WmTests:LetterboxUiControllerTest
Test: atest WmTests:SizeCompatTests
Test: atest WmTests:TransparentPolicyTest
Change-Id: Ifbc3c9e37d48f4dfb1e2ffda06f57511fac512c3
5 files changed, 567 insertions, 241 deletions
diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java b/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java index fbe90a2cecda..10f3e833f78a 100644 --- a/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java +++ b/services/core/java/com/android/server/wm/AppCompatOrientationCapability.java @@ -38,6 +38,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.server.wm.utils.OptPropFactory; import java.util.function.BooleanSupplier; +import java.util.function.LongSupplier; class AppCompatOrientationCapability { @@ -58,7 +59,8 @@ class AppCompatOrientationCapability { @NonNull LetterboxConfiguration letterboxConfiguration, @NonNull ActivityRecord activityRecord) { mActivityRecord = activityRecord; - mOrientationCapabilityState = new OrientationCapabilityState(mActivityRecord); + mOrientationCapabilityState = new OrientationCapabilityState(mActivityRecord, + System::currentTimeMillis); final BooleanSupplier isPolicyForIgnoringRequestedOrientationEnabled = asLazy( letterboxConfiguration::isPolicyForIgnoringRequestedOrientationEnabled); mIgnoreRequestedOrientationOptProp = optPropBuilder.create( @@ -214,8 +216,12 @@ class AppCompatOrientationCapability { private long mTimeMsLastSetOrientationRequest = 0; // Counter for ActivityRecord#setRequestedOrientation private int mSetOrientationRequestCounter = 0; + @VisibleForTesting + LongSupplier mCurrentTimeMillisSupplier; - OrientationCapabilityState(@NonNull ActivityRecord activityRecord) { + OrientationCapabilityState(@NonNull ActivityRecord activityRecord, + @NonNull LongSupplier currentTimeMillisSupplier) { + mCurrentTimeMillisSupplier = currentTimeMillisSupplier; mIsOverrideToNosensorOrientationEnabled = activityRecord.info.isChangeEnabled(OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR); mIsOverrideToPortraitOrientationEnabled = @@ -238,7 +244,7 @@ class AppCompatOrientationCapability { * Updates the orientation request counter using a specific timeout. */ void updateOrientationRequestLoopState() { - final long currTimeMs = System.currentTimeMillis(); + final long currTimeMs = mCurrentTimeMillisSupplier.getAsLong(); final long elapsedTime = currTimeMs - mTimeMsLastSetOrientationRequest; if (elapsedTime < SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS) { mSetOrientationRequestCounter++; diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationCapabilityTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationCapabilityTest.java new file mode 100644 index 000000000000..f1cf866df4a5 --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatOrientationCapabilityTest.java @@ -0,0 +1,433 @@ +/* + * 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 android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; +import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; +import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION; +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; +import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; +import static com.android.server.wm.AppCompatOrientationCapability.OrientationCapabilityState.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; +import static com.android.server.wm.AppCompatOrientationCapability.OrientationCapabilityState.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; + +import android.compat.testing.PlatformCompatChangeRule; +import android.content.ComponentName; +import android.content.pm.PackageManager; +import android.content.res.Configuration; +import android.platform.test.annotations.Presubmit; + +import androidx.annotation.NonNull; + +import com.android.server.wm.utils.TestComponentStack; + +import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; + +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.IntConsumer; +import java.util.function.LongSupplier; + +/** + * Test class for {@link AppCompatOrientationCapability}. + * <p> + * Build/Install/Run: + * atest WmTests:AppCompatOrientationCapabilityTest + */ +@Presubmit +@RunWith(WindowTestRunner.class) +public class AppCompatOrientationCapabilityTest extends WindowTestsBase { + + @Rule + public TestRule compatChangeRule = new PlatformCompatChangeRule(); + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) + public void testShouldIgnoreRequestedOrientation_activityRelaunching_returnsTrue() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareRelaunchingAfterRequestedOrientationChanged(true); + + robot.checkShouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) + public void testShouldIgnoreRequestedOrientation_cameraCompatTreatment_returnsTrue() { + runTestScenario((robot) -> { + robot.prepareIsCameraCompatTreatmentEnabled(true); + robot.prepareIsCameraCompatTreatmentEnabledAtBuildTime(true); + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + + robot.createActivityWithComponentInNewTask(); + robot.prepareRelaunchingAfterRequestedOrientationChanged(false); + robot.prepareIsTreatmentEnabledForTopActivity(true); + + robot.checkShouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); + }); + } + + @Test + public void testShouldIgnoreRequestedOrientation_overrideDisabled_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + + robot.createActivityWithComponent(); + robot.prepareRelaunchingAfterRequestedOrientationChanged(true); + + robot.checkShouldNotIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); + }); + } + + @Test + public void testShouldIgnoreRequestedOrientation_propertyIsTrue_returnsTrue() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.enableProperty(PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION); + + robot.createActivityWithComponent(); + robot.prepareRelaunchingAfterRequestedOrientationChanged(true); + + robot.checkShouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) + public void testShouldIgnoreRequestedOrientation_propertyIsFalseAndOverride_returnsFalse() + throws Exception { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.disableProperty(PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION); + + robot.createActivityWithComponent(); + robot.prepareRelaunchingAfterRequestedOrientationChanged(true); + + robot.checkShouldNotIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); + }); + } + + @Test + public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(false); + + robot.checkRequestLoopExtended((i) -> { + robot.checkShouldNotIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ 0); + }); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) + public void testShouldIgnoreOrientationRequestLoop_propertyIsFalseAndOverride_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.disableProperty( + PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(false); + + robot.checkRequestLoopExtended((i) -> { + robot.checkShouldNotIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ 0); + }); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) + public void testShouldIgnoreOrientationRequestLoop_isLetterboxed_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(true); + + robot.checkRequestLoopExtended((i) -> { + robot.checkShouldNotIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ i); + }); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) + public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(false); + + robot.checkShouldNotIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ 0); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) + public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(false); + + robot.prepareMockedTime(); + robot.checkRequestLoopExtended((i) -> { + robot.checkShouldNotIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ 0); + robot.delay(); + }); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) + public void testShouldIgnoreOrientationRequestLoop_returnsTrue() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(false); + + robot.checkRequestLoop((i) -> { + robot.checkShouldNotIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ i); + }); + robot.checkShouldIgnoreOrientationLoop(); + robot.checkExpectedLoopCount(/* expectedCount */ MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP); + }); + } + + @Test + @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH}) + public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() { + runTestScenario((robot) -> { + robot.prepareIsPolicyForIgnoringRequestedOrientationEnabled(true); + robot.createActivityWithComponent(); + robot.prepareIsLetterboxedForFixedOrientationAndAspectRatio(false); + + robot.checkShouldNotIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED); + }); + } + + /** + * Runs a test scenario providing a Robot. + */ + void runTestScenario(@NonNull Consumer<OrientationCapabilityRobotTest> consumer) { + spyOn(mWm.mLetterboxConfiguration); + final OrientationCapabilityRobotTest robot = + new OrientationCapabilityRobotTest(mWm, mAtm, mSupervisor); + consumer.accept(robot); + } + + private static class OrientationCapabilityRobotTest { + + @NonNull + private final ActivityTaskManagerService mAtm; + @NonNull + private final WindowManagerService mWm; + @NonNull + private final ActivityTaskSupervisor mSupervisor; + @NonNull + private final LetterboxConfiguration mLetterboxConfiguration; + @NonNull + private final TestComponentStack<ActivityRecord> mActivityStack; + @NonNull + private final TestComponentStack<Task> mTaskStack; + @NonNull + private final CurrentTimeMillisSupplierTest mTestCurrentTimeMillisSupplier; + + + OrientationCapabilityRobotTest(@NonNull WindowManagerService wm, + @NonNull ActivityTaskManagerService atm, + @NonNull ActivityTaskSupervisor supervisor) { + mAtm = atm; + mWm = wm; + mSupervisor = supervisor; + mActivityStack = new TestComponentStack<>(); + mTaskStack = new TestComponentStack<>(); + mLetterboxConfiguration = mWm.mLetterboxConfiguration; + mTestCurrentTimeMillisSupplier = new CurrentTimeMillisSupplierTest(); + } + + void prepareRelaunchingAfterRequestedOrientationChanged(boolean enabled) { + getTopOrientationCapability().setRelaunchingAfterRequestedOrientationChanged(enabled); + } + + void prepareIsPolicyForIgnoringRequestedOrientationEnabled(boolean enabled) { + doReturn(enabled).when(mLetterboxConfiguration) + .isPolicyForIgnoringRequestedOrientationEnabled(); + } + + void prepareIsCameraCompatTreatmentEnabled(boolean enabled) { + doReturn(enabled).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(); + } + + void prepareIsCameraCompatTreatmentEnabledAtBuildTime(boolean enabled) { + doReturn(enabled).when(mLetterboxConfiguration) + .isCameraCompatTreatmentEnabledAtBuildTime(); + } + + void prepareIsTreatmentEnabledForTopActivity(boolean enabled) { + final DisplayRotationCompatPolicy displayPolicy = mActivityStack.top() + .mDisplayContent.mDisplayRotationCompatPolicy; + spyOn(displayPolicy); + doReturn(enabled).when(displayPolicy) + .isTreatmentEnabledForActivity(eq(mActivityStack.top())); + } + + // Useful to reduce timeout during tests + void prepareMockedTime() { + getTopOrientationCapability().mOrientationCapabilityState.mCurrentTimeMillisSupplier = + mTestCurrentTimeMillisSupplier; + } + + void delay() { + mTestCurrentTimeMillisSupplier.delay(SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS); + } + + void enableProperty(@NonNull String propertyName) { + setPropertyValue(propertyName, /* enabled */ true); + } + + void disableProperty(@NonNull String propertyName) { + setPropertyValue(propertyName, /* enabled */ false); + } + + void prepareIsLetterboxedForFixedOrientationAndAspectRatio(boolean enabled) { + spyOn(mActivityStack.top()); + doReturn(enabled).when(mActivityStack.top()) + .isLetterboxedForFixedOrientationAndAspectRatio(); + } + + void createActivityWithComponent() { + createActivityWithComponentInNewTask(/* inNewTask */ mTaskStack.isEmpty()); + } + + void createActivityWithComponentInNewTask() { + createActivityWithComponentInNewTask(/* inNewTask */ true); + } + + private void createActivityWithComponentInNewTask(boolean inNewTask) { + if (inNewTask) { + createNewTask(); + } + final ActivityRecord activity = new ActivityBuilder(mAtm) + .setOnTop(true) + .setTask(mTaskStack.top()) + // Set the component to be that of the test class in order + // to enable compat changes + .setComponent(ComponentName.createRelative(mAtm.mContext, + com.android.server.wm.LetterboxUiControllerTest.class.getName())) + .build(); + mActivityStack.push(activity); + } + + void checkShouldIgnoreRequestedOrientation( + @Configuration.Orientation int expectedOrientation) { + assertTrue(getTopOrientationCapability() + .shouldIgnoreRequestedOrientation(expectedOrientation)); + } + + void checkShouldNotIgnoreRequestedOrientation( + @Configuration.Orientation int expectedOrientation) { + assertFalse(getTopOrientationCapability() + .shouldIgnoreRequestedOrientation(expectedOrientation)); + } + + void checkExpectedLoopCount(int expectedCount) { + assertEquals(expectedCount, getTopOrientationCapability() + .getSetOrientationRequestCounter()); + } + + void checkShouldNotIgnoreOrientationLoop() { + assertFalse(getTopOrientationCapability().shouldIgnoreOrientationRequestLoop()); + } + + void checkShouldIgnoreOrientationLoop() { + assertTrue(getTopOrientationCapability().shouldIgnoreOrientationRequestLoop()); + } + + void checkRequestLoop(IntConsumer consumer) { + for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { + consumer.accept(i); + } + } + + void checkRequestLoopExtended(IntConsumer consumer) { + for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { + consumer.accept(i); + } + } + + private AppCompatOrientationCapability getTopOrientationCapability() { + return mActivityStack.top().mAppCompatController.getAppCompatCapability() + .getAppCompatOrientationCapability(); + } + + private void createNewTask() { + final DisplayContent displayContent = new TestDisplayContent + .Builder(mAtm, /* dw */ 1000, /* dh */ 2000).build(); + final Task newTask = new TaskBuilder(mSupervisor).setDisplay(displayContent).build(); + mTaskStack.push(newTask); + } + + private void setPropertyValue(@NonNull String propertyName, boolean enabled) { + PackageManager.Property property = new PackageManager.Property(propertyName, + /* value */ enabled, /* packageName */ "", + /* className */ ""); + PackageManager pm = mWm.mContext.getPackageManager(); + spyOn(pm); + try { + doReturn(property).when(pm).getProperty(eq(propertyName), anyString()); + } catch (PackageManager.NameNotFoundException e) { + fail(e.getLocalizedMessage()); + } + } + + private static class CurrentTimeMillisSupplierTest implements LongSupplier { + + private long mCurrenTimeMillis = System.currentTimeMillis(); + + @Override + public long getAsLong() { + return mCurrenTimeMillis; + } + + public void delay(long delay) { + mCurrenTimeMillis += delay; + } + } + } +} diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java index 07870527c8fd..b1200bcdd4b7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java @@ -25,8 +25,6 @@ import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FRE import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH; import static android.content.pm.ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; -import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; -import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static android.content.pm.ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO; import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_ONLY_FOR_CAMERA; @@ -50,21 +48,17 @@ import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_FORCE_ROTA import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ALLOW_REFRESH; import static android.view.WindowManager.PROPERTY_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_DISPLAY_ORIENTATION_OVERRIDE; -import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_ORIENTATION_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE; import static android.view.WindowManager.PROPERTY_COMPAT_ENABLE_FAKE_FOCUS; -import static android.view.WindowManager.PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; -import static com.android.server.wm.AppCompatOrientationCapability.OrientationCapabilityState.MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; -import static com.android.server.wm.AppCompatOrientationCapability.OrientationCapabilityState.SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS; import static com.android.window.flags.Flags.FLAG_CAMERA_COMPAT_FOR_FREEFORM; import static org.junit.Assert.assertEquals; @@ -149,187 +143,6 @@ public class LetterboxUiControllerTest extends WindowTestsBase { mController = new LetterboxUiController(mWm, mActivity); } - // shouldIgnoreRequestedOrientation - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) - public void testShouldIgnoreRequestedOrientation_activityRelaunching_returnsTrue() { - prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - - assertTrue(mActivity.mAppCompatController.getAppCompatCapability() - .getAppCompatOrientationCapability() - .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) - public void testShouldIgnoreRequestedOrientation_cameraCompatTreatment_returnsTrue() { - doReturn(true).when(mLetterboxConfiguration).isCameraCompatTreatmentEnabled(); - doReturn(true).when(mLetterboxConfiguration) - .isCameraCompatTreatmentEnabledAtBuildTime(); - - // Recreate DisplayContent with DisplayRotationCompatPolicy - mActivity = setUpActivityWithComponent(); - mController = new LetterboxUiController(mWm, mActivity); - prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - mController.setRelaunchingAfterRequestedOrientationChanged(false); - - spyOn(mDisplayContent.mDisplayRotationCompatPolicy); - doReturn(true).when(mDisplayContent.mDisplayRotationCompatPolicy) - .isTreatmentEnabledForActivity(eq(mActivity)); - - assertTrue(mActivity.mAppCompatController.getAppCompatCapability() - .getAppCompatOrientationCapability() - .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); - } - - @Test - public void testShouldIgnoreRequestedOrientation_overrideDisabled_returnsFalse() { - prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - - assertFalse(mActivity.mAppCompatController.getAppCompatCapability() - .getAppCompatOrientationCapability() - .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); - } - - @Test - public void testShouldIgnoreRequestedOrientation_propertyIsTrue_returnsTrue() - throws Exception { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - mockThatProperty(PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION, /* value */ true); - mController = new LetterboxUiController(mWm, mActivity); - prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - - assertTrue(mActivity.mAppCompatController.getAppCompatCapability() - .getAppCompatOrientationCapability() - .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) - public void testShouldIgnoreRequestedOrientation_propertyIsFalseAndOverride_returnsFalse() - throws Exception { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - mockThatProperty(PROPERTY_COMPAT_IGNORE_REQUESTED_ORIENTATION, /* value */ false); - - mController = new LetterboxUiController(mWm, mActivity); - prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - - assertFalse(mActivity.mAppCompatController.getAppCompatCapability() - .getAppCompatOrientationCapability() - .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); - } - - @Test - public void testShouldIgnoreOrientationRequestLoop_overrideDisabled_returnsFalse() { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); - // Request 3 times to simulate orientation request loop - for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, - /* expectedCount */ 0); - } - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) - public void testShouldIgnoreOrientationRequestLoop_propertyIsFalseAndOverride_returnsFalse() - throws Exception { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - mockThatProperty(PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED, - /* value */ false); - doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); - - mController = new LetterboxUiController(mWm, mActivity); - - // Request 3 times to simulate orientation request loop - for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, - /* expectedCount */ 0); - } - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) - public void testShouldIgnoreOrientationRequestLoop_isLetterboxed_returnsFalse() { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - doReturn(true).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); - - // Request 3 times to simulate orientation request loop - for (int i = 0; i <= MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, - /* expectedCount */ i); - } - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) - public void testShouldIgnoreOrientationRequestLoop_noLoop_returnsFalse() { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); - - // No orientation request loop - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, - /* expectedCount */ 0); - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) - public void testShouldIgnoreOrientationRequestLoop_timeout_returnsFalse() - throws InterruptedException { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); - - for (int i = MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i > 0; i--) { - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, - /* expectedCount */ 0); - Thread.sleep(SET_ORIENTATION_REQUEST_COUNTER_TIMEOUT_MS); - } - } - - @Test - @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED}) - public void testShouldIgnoreOrientationRequestLoop_returnsTrue() { - doReturn(true).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - doReturn(false).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio(); - - for (int i = 0; i < MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP; i++) { - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ false, - /* expectedCount */ i); - } - assertShouldIgnoreOrientationRequestLoop(/* shouldIgnore */ true, - /* expectedCount */ MIN_COUNT_TO_IGNORE_REQUEST_IN_LOOP); - } - - private void assertShouldIgnoreOrientationRequestLoop(boolean shouldIgnore, int expectedCount) { - if (shouldIgnore) { - assertTrue(mController.shouldIgnoreOrientationRequestLoop()); - } else { - assertFalse(mController.shouldIgnoreOrientationRequestLoop()); - } - assertEquals(expectedCount, mController.getSetOrientationRequestCounter()); - } - - @Test - @EnableCompatChanges({OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH}) - public void testShouldIgnoreRequestedOrientation_flagIsDisabled_returnsFalse() { - prepareActivityThatShouldIgnoreRequestedOrientationDuringRelaunch(); - doReturn(false).when(mLetterboxConfiguration) - .isPolicyForIgnoringRequestedOrientationEnabled(); - - assertFalse(mActivity.mAppCompatController.getAppCompatCapability() - .getAppCompatOrientationCapability() - .shouldIgnoreRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED)); - } - // shouldRefreshActivityForCameraCompat @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java index 78cea954eceb..628c65e992fd 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransparentPolicyTest.java @@ -46,12 +46,14 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.platform.test.annotations.Presubmit; +import androidx.annotation.NonNull; + +import com.android.server.wm.utils.TestComponentStack; + import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; -import java.util.ArrayList; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; @@ -318,20 +320,22 @@ public class TransparentPolicyTest extends WindowTestsBase { */ private static class TransparentPolicyRobotTest { + @NonNull private final ActivityTaskManagerService mAtm; - + @NonNull private final Task mTask; - - private final ActivityStackTest mActivityStack; - + @NonNull + private final TestComponentStack<ActivityRecord> mActivityStack; + @NonNull private WindowConfiguration mTopActivityWindowConfiguration; - private TransparentPolicyRobotTest(ActivityTaskManagerService atm, Task task, - ActivityRecord opaqueActivity) { + private TransparentPolicyRobotTest(@NonNull ActivityTaskManagerService atm, + @NonNull Task task, + @NonNull ActivityRecord opaqueActivity) { mAtm = atm; mTask = task; - mActivityStack = new ActivityStackTest(); - mActivityStack.pushActivity(opaqueActivity); + mActivityStack = new TestComponentStack<>(); + mActivityStack.push(opaqueActivity); spyOn(opaqueActivity.mAppCompatController.getTransparentPolicy()); } @@ -361,7 +365,7 @@ public class TransparentPolicyTest extends WindowTestsBase { mTask.addChild(newActivity); } spyOn(newActivity.mAppCompatController.getTransparentPolicy()); - mActivityStack.pushActivity(newActivity); + mActivityStack.push(newActivity); } void attachTopActivityToTask() { @@ -596,45 +600,5 @@ public class TransparentPolicyTest extends WindowTestsBase { display.computeScreenConfiguration(c); display.onRequestedOverrideConfigurationChanged(c); } - - /** - * Contains all the ActivityRecord launched in the test. This is different from what's in - * the Task because activities are added here even if not added to tasks. - */ - private static class ActivityStackTest { - private final List<ActivityRecord> mActivities = new ArrayList<>(); - - void pushActivity(ActivityRecord activityRecord) { - mActivities.add(activityRecord); - } - - void applyToTop(Consumer<ActivityRecord> consumer) { - consumer.accept(top()); - } - - ActivityRecord getFromTop(int fromTop) { - return mActivities.get(mActivities.size() - fromTop - 1); - } - - ActivityRecord base() { - return mActivities.get(0); - } - - ActivityRecord top() { - return mActivities.get(mActivities.size() - 1); - } - - // Allows access to the activity at position beforeLast from the top. - // If fromTop = 0 the activity used is the top one. - void applyTo(int fromTop, Consumer<ActivityRecord> consumer) { - consumer.accept(getFromTop(fromTop)); - } - - void applyToAll(Consumer<ActivityRecord> consumer) { - for (int i = mActivities.size() - 1; i >= 0; i--) { - consumer.accept(mActivities.get(i)); - } - } - } } } diff --git a/services/tests/wmtests/src/com/android/server/wm/utils/TestComponentStack.java b/services/tests/wmtests/src/com/android/server/wm/utils/TestComponentStack.java new file mode 100644 index 000000000000..a06c0a216d9e --- /dev/null +++ b/services/tests/wmtests/src/com/android/server/wm/utils/TestComponentStack.java @@ -0,0 +1,110 @@ +/* + * 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.utils; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +/** + * Contains all the component created in the test. + */ +public class TestComponentStack<T> { + + @NonNull + private final List<T> mItems = new ArrayList<>(); + + /** + * Adds an item to the stack. + * + * @param item The item to add. + */ + public void push(@NonNull T item) { + mItems.add(item); + } + + /** + * Consumes the top element of the stack. + * + * @param consumer Consumer for the optional top element. + * @throws IndexOutOfBoundsException In case that stack is empty. + */ + public void applyToTop(@NonNull Consumer<T> consumer) { + consumer.accept(top()); + } + + /** + * Returns the item at fromTop position from the top one if present or it throws an + * exception if not present. + * + * @param fromTop The position from the top of the item to return. + * @return The returned item. + * @throws IndexOutOfBoundsException In case that position doesn't exist. + */ + @NonNull + public T getFromTop(int fromTop) { + return mItems.get(mItems.size() - fromTop - 1); + } + + /** + * @return The item at the base of the stack if present. + * @throws IndexOutOfBoundsException In case that stack is empty. + */ + @NonNull + public T base() { + return mItems.get(0); + } + + /** + * @return The item at the top of the stack if present. + * @throws IndexOutOfBoundsException In case that stack is empty. + */ + @NonNull + public T top() { + return mItems.get(mItems.size() - 1); + } + + /** + * @return {@code true} if the stack is empty. + */ + public boolean isEmpty() { + return mItems.isEmpty(); + } + + /** + * Allows access to the item at position beforeLast from the top. + * + * @param fromTop The position from the top of the item to return. + * @param consumer Consumer for the optional returned element. + */ + public void applyTo(int fromTop, @NonNull Consumer<T> consumer) { + consumer.accept(getFromTop(fromTop)); + } + + /** + * Invoked the consumer iterating over all the elements in the stack. + * + * @param consumer Consumer for the elements. + */ + public void applyToAll(@NonNull Consumer<T> consumer) { + for (int i = mItems.size() - 1; i >= 0; i--) { + consumer.accept(mItems.get(i)); + } + } +} |