1 /* 2 * Copyright 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 20 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 21 import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxInnerBounds; 22 import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxOuterBounds; 23 import static com.android.server.wm.AppCompatLetterboxUtils.calculateLetterboxPosition; 24 25 import static org.mockito.Mockito.mock; 26 27 import android.graphics.Point; 28 import android.graphics.Rect; 29 import android.platform.test.annotations.Presubmit; 30 31 import androidx.annotation.NonNull; 32 import androidx.test.filters.SmallTest; 33 34 import org.junit.Assert; 35 import org.junit.Test; 36 import org.junit.runner.RunWith; 37 38 import java.util.function.Consumer; 39 40 /** 41 * Tests for the {@link AppCompatLetterboxUtils} class. 42 * 43 * Build/Install/Run: 44 * atest WmTests:AppCompatLetterboxUtilsTest 45 */ 46 @SmallTest 47 @Presubmit 48 @RunWith(WindowTestRunner.class) 49 public class AppCompatLetterboxUtilsTest extends WindowTestsBase { 50 51 @Test allEmptyWhenIsAppNotLetterboxed()52 public void allEmptyWhenIsAppNotLetterboxed() { 53 runTestScenario((robot) -> { 54 robot.activity().createActivityWithComponent(); 55 robot.setTopActivityLetterboxPolicyRunning(false); 56 robot.getLetterboxPosition(); 57 robot.assertPosition(/* x */ 0, /* y */0); 58 robot.getInnerBounds(); 59 robot.assertInnerBounds(/* left */ 0, /* top */ 0, /* right */ 0, /* bottom */ 0); 60 robot.getOuterBounds(); 61 robot.assertOuterBounds(/* left */ 0, /* top */ 0, /* right */ 0, /* bottom */ 0); 62 }); 63 } 64 65 @Test positionIsFromActivity()66 public void positionIsFromActivity() { 67 runTestScenario((robot) -> { 68 robot.activity().createActivityWithComponent(); 69 robot.setTopActivityLetterboxPolicyRunning(true); 70 robot.activity().configureTopActivityBounds( 71 new Rect(/* left */ 200, /* top */ 400, /* right */ 300, /* bottom */ 400)); 72 robot.getLetterboxPosition(); 73 74 robot.assertPosition(/* x */ 200, /* y */ 400); 75 }); 76 } 77 78 @Test outerBoundsWhenFixedRotationTransformDisplayBoundsIsAvailable()79 public void outerBoundsWhenFixedRotationTransformDisplayBoundsIsAvailable() { 80 runTestScenario((robot) -> { 81 robot.activity().createActivityWithComponent(); 82 robot.setTopActivityLetterboxPolicyRunning(true); 83 robot.activity().setFixedRotationTransformDisplayBounds( 84 new Rect(/* left */ 1, /* top */ 2, /* right */ 3, /* bottom */ 4)); 85 robot.getOuterBounds(); 86 87 robot.assertOuterBounds(/* left */ 1, /* top */ 2, /* right */ 3, /* bottom */ 4); 88 }); 89 } 90 91 @Test outerBoundsNoFixedRotationTransformDisplayBoundsInMultiWindow()92 public void outerBoundsNoFixedRotationTransformDisplayBoundsInMultiWindow() { 93 runTestScenario((robot) -> { 94 robot.activity().createActivityWithComponent(); 95 robot.setTopActivityLetterboxPolicyRunning(true); 96 robot.activity().setFixedRotationTransformDisplayBounds(null); 97 robot.activity().setTopActivityInMultiWindowMode(true); 98 robot.getOuterBounds(); 99 100 robot.checkOuterBoundsAreTaskFragmentBounds(); 101 }); 102 } 103 104 @Test outerBoundsNoFixedRotationTransformDisplayBoundsNotInMultiWindow()105 public void outerBoundsNoFixedRotationTransformDisplayBoundsNotInMultiWindow() { 106 runTestScenario((robot) -> { 107 robot.activity().createActivityWithComponent(); 108 robot.setTopActivityLetterboxPolicyRunning(true); 109 robot.activity().setFixedRotationTransformDisplayBounds(null); 110 robot.activity().setTopActivityInMultiWindowMode(false); 111 robot.getOuterBounds(); 112 113 robot.checkOuterBoundsAreRootTaskParentBounds(); 114 }); 115 } 116 117 @Test innerBoundsTransparencyPolicyIsRunning()118 public void innerBoundsTransparencyPolicyIsRunning() { 119 runTestScenario((robot) -> { 120 robot.activity().createActivityWithComponent(); 121 robot.setTopActivityLetterboxPolicyRunning(true); 122 robot.setTopActivityTransparentPolicyRunning(true); 123 124 robot.getInnerBounds(); 125 126 robot.checkInnerBoundsAreActivityBounds(); 127 }); 128 } 129 130 @Test innerBoundsTransparencyPolicyIsNotRunning()131 public void innerBoundsTransparencyPolicyIsNotRunning() { 132 runTestScenario((robot) -> { 133 robot.activity().createActivityWithComponent(); 134 robot.setTopActivityLetterboxPolicyRunning(true); 135 robot.setTopActivityTransparentPolicyRunning(false); 136 robot.setWindowFrame( 137 new Rect(/* left */ 100, /* top */ 200, /* right */ 300, /* bottom */ 400)); 138 139 robot.getInnerBounds(); 140 141 robot.assertInnerBounds(/* left */ 100, /* top */ 200, /* right */ 300, /* bottom */ 142 400); 143 }); 144 } 145 146 /** 147 * Runs a test scenario providing a Robot. 148 */ runTestScenario(@onNull Consumer<LetterboxUtilsRobotTest> consumer)149 void runTestScenario(@NonNull Consumer<LetterboxUtilsRobotTest> consumer) { 150 final LetterboxUtilsRobotTest robot = new LetterboxUtilsRobotTest(mWm, mAtm, mSupervisor); 151 consumer.accept(robot); 152 } 153 154 private static class LetterboxUtilsRobotTest extends AppCompatRobotBase { 155 156 private final Point mPosition = new Point(); 157 private final Rect mInnerBound = new Rect(); 158 private final Rect mOuterBound = new Rect(); 159 160 @NonNull 161 private final WindowState mWindowState; 162 LetterboxUtilsRobotTest(@onNull WindowManagerService wm, @NonNull ActivityTaskManagerService atm, @NonNull ActivityTaskSupervisor supervisor)163 LetterboxUtilsRobotTest(@NonNull WindowManagerService wm, 164 @NonNull ActivityTaskManagerService atm, 165 @NonNull ActivityTaskSupervisor supervisor) { 166 super(wm, atm, supervisor); 167 mWindowState = mock(WindowState.class); 168 } 169 170 @Override onPostActivityCreation(@onNull ActivityRecord activity)171 void onPostActivityCreation(@NonNull ActivityRecord activity) { 172 super.onPostActivityCreation(activity); 173 spyOn(activity.mAppCompatController.getLetterboxPolicy()); 174 spyOn(activity.mAppCompatController.getTransparentPolicy()); 175 } 176 setTopActivityLetterboxPolicyRunning(boolean running)177 void setTopActivityLetterboxPolicyRunning(boolean running) { 178 doReturn(running).when(activity().top().mAppCompatController 179 .getLetterboxPolicy()).isRunning(); 180 } 181 setTopActivityTransparentPolicyRunning(boolean running)182 void setTopActivityTransparentPolicyRunning(boolean running) { 183 doReturn(running).when(activity().top().mAppCompatController 184 .getTransparentPolicy()).isRunning(); 185 } 186 setWindowFrame(@onNull Rect frame)187 void setWindowFrame(@NonNull Rect frame) { 188 doReturn(frame).when(mWindowState).getFrame(); 189 } 190 getLetterboxPosition()191 void getLetterboxPosition() { 192 calculateLetterboxPosition(activity().top(), mPosition); 193 } 194 getInnerBounds()195 void getInnerBounds() { 196 calculateLetterboxInnerBounds(activity().top(), mWindowState, mInnerBound); 197 } 198 getOuterBounds()199 void getOuterBounds() { 200 calculateLetterboxOuterBounds(activity().top(), mOuterBound); 201 } 202 assertPosition(int expectedX, int expectedY)203 void assertPosition(int expectedX, int expectedY) { 204 Assert.assertEquals(expectedX, mPosition.x); 205 Assert.assertEquals(expectedY, mPosition.y); 206 } 207 assertInnerBounds(int expectedLeft, int expectedTop, int expectedRight, int expectedBottom)208 void assertInnerBounds(int expectedLeft, int expectedTop, int expectedRight, 209 int expectedBottom) { 210 Assert.assertEquals(expectedLeft, mInnerBound.left); 211 Assert.assertEquals(expectedTop, mInnerBound.top); 212 Assert.assertEquals(expectedRight, mInnerBound.right); 213 Assert.assertEquals(expectedBottom, mInnerBound.bottom); 214 } 215 assertOuterBounds(int expectedLeft, int expectedTop, int expectedRight, int expectedBottom)216 void assertOuterBounds(int expectedLeft, int expectedTop, int expectedRight, 217 int expectedBottom) { 218 Assert.assertEquals(expectedLeft, mOuterBound.left); 219 Assert.assertEquals(expectedTop, mOuterBound.top); 220 Assert.assertEquals(expectedRight, mOuterBound.right); 221 Assert.assertEquals(expectedBottom, mOuterBound.bottom); 222 } 223 checkOuterBoundsAreRootTaskParentBounds()224 void checkOuterBoundsAreRootTaskParentBounds() { 225 Assert.assertEquals(mOuterBound, 226 activity().top().getRootTask().getParent().getBounds()); 227 } 228 checkOuterBoundsAreTaskFragmentBounds()229 void checkOuterBoundsAreTaskFragmentBounds() { 230 Assert.assertEquals(mOuterBound, 231 activity().top().getTaskFragment().getBounds()); 232 } 233 checkInnerBoundsAreActivityBounds()234 void checkInnerBoundsAreActivityBounds() { 235 Assert.assertEquals(mInnerBound, activity().top().getBounds()); 236 } 237 238 } 239 } 240