1 /* 2 * Copyright (C) 2022 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 android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 20 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 21 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 22 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 23 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 24 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 25 import static android.content.res.Configuration.ORIENTATION_UNDEFINED; 26 27 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 28 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy; 30 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 31 32 import static org.junit.Assert.assertFalse; 33 import static org.junit.Assert.assertTrue; 34 35 import android.platform.test.annotations.Presubmit; 36 import android.view.Surface; 37 import android.view.WindowInsets.Type; 38 39 import androidx.test.filters.SmallTest; 40 41 import org.junit.Before; 42 import org.junit.Test; 43 import org.junit.runner.RunWith; 44 45 /** 46 * Test class for {@link DisplayRotationImmersiveAppCompatPolicy}. 47 * 48 * Build/Install/Run: 49 * atest WmTests:DisplayRotationImmersiveAppCompatPolicyTests 50 */ 51 @SmallTest 52 @Presubmit 53 @RunWith(WindowTestRunner.class) 54 public class DisplayRotationImmersiveAppCompatPolicyTests extends WindowTestsBase { 55 56 private DisplayRotationImmersiveAppCompatPolicy mPolicy; 57 58 private LetterboxConfiguration mMockLetterboxConfiguration; 59 private ActivityRecord mMockActivityRecord; 60 private Task mMockTask; 61 private WindowState mMockWindowState; 62 63 @Before setUp()64 public void setUp() throws Exception { 65 mMockActivityRecord = mock(ActivityRecord.class); 66 mMockTask = mock(Task.class); 67 when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_FULLSCREEN); 68 when(mMockActivityRecord.getTask()).thenReturn(mMockTask); 69 when(mMockActivityRecord.areBoundsLetterboxed()).thenReturn(false); 70 when(mMockActivityRecord.getRequestedConfigurationOrientation()).thenReturn( 71 ORIENTATION_LANDSCAPE); 72 mMockWindowState = mock(WindowState.class); 73 when(mMockWindowState.getRequestedVisibleTypes()).thenReturn(0); 74 when(mMockActivityRecord.findMainWindow()).thenReturn(mMockWindowState); 75 76 spy(mDisplayContent); 77 doReturn(mMockActivityRecord).when(mDisplayContent).topRunningActivity(); 78 when(mDisplayContent.getIgnoreOrientationRequest()).thenReturn(true); 79 80 mMockLetterboxConfiguration = mock(LetterboxConfiguration.class); 81 when(mMockLetterboxConfiguration.isDisplayRotationImmersiveAppCompatPolicyEnabled()) 82 .thenReturn(true); 83 when(mMockLetterboxConfiguration 84 .isDisplayRotationImmersiveAppCompatPolicyEnabledAtBuildTime()) 85 .thenReturn(true); 86 87 mPolicy = DisplayRotationImmersiveAppCompatPolicy.createIfNeeded( 88 mMockLetterboxConfiguration, createDisplayRotationMock(), 89 mDisplayContent); 90 } 91 createDisplayRotationMock()92 private DisplayRotation createDisplayRotationMock() { 93 DisplayRotation mockDisplayRotation = mock(DisplayRotation.class); 94 95 when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_0)).thenReturn(true); 96 when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_90)).thenReturn(false); 97 when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_180)).thenReturn(true); 98 when(mockDisplayRotation.isAnyPortrait(Surface.ROTATION_270)).thenReturn(false); 99 when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_0)).thenReturn(false); 100 when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_90)).thenReturn(true); 101 when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_180)).thenReturn(false); 102 when(mockDisplayRotation.isLandscapeOrSeascape(Surface.ROTATION_270)).thenReturn(true); 103 104 return mockDisplayRotation; 105 } 106 107 @Test testIsRotationLockEnforced_landscapeActivity_lockedWhenRotatingToPortrait()108 public void testIsRotationLockEnforced_landscapeActivity_lockedWhenRotatingToPortrait() { 109 // Base case: App is optimal in Landscape. 110 111 // ROTATION_* is the target display orientation counted from the natural display 112 // orientation. Outside of test environment, ROTATION_0 means that proposed display 113 // rotation is the natural device orientation. 114 // DisplayRotationImmersiveAppCompatPolicy assesses whether the proposed target 115 // orientation ROTATION_* is optimal for the top fullscreen activity or not. 116 // For instance, ROTATION_0 means portrait screen orientation (see 117 // createDisplayRotationMock) which isn't optimal for a landscape-only activity so 118 // we should show a rotation suggestion button instead of rotating directly. 119 120 // Rotation to portrait 121 assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_0)); 122 // Rotation to landscape 123 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_90)); 124 // Rotation to portrait 125 assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_180)); 126 // Rotation to landscape 127 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_270)); 128 } 129 130 @Test testIsRotationLockEnforced_portraitActivity_lockedWhenRotatingToLandscape()131 public void testIsRotationLockEnforced_portraitActivity_lockedWhenRotatingToLandscape() { 132 when(mMockActivityRecord.getRequestedConfigurationOrientation()).thenReturn( 133 ORIENTATION_PORTRAIT); 134 135 // Rotation to portrait 136 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_0)); 137 // Rotation to landscape 138 assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_90)); 139 // Rotation to portrait 140 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_180)); 141 // Rotation to landscape 142 assertTrue(mPolicy.isRotationLockEnforced(Surface.ROTATION_270)); 143 } 144 145 @Test testIsRotationLockEnforced_responsiveActivity_lockNotEnforced()146 public void testIsRotationLockEnforced_responsiveActivity_lockNotEnforced() { 147 // Do not fix screen orientation 148 when(mMockActivityRecord.getRequestedConfigurationOrientation()).thenReturn( 149 ORIENTATION_UNDEFINED); 150 151 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 152 } 153 154 @Test testIsRotationLockEnforced_statusBarVisible_lockNotEnforced()155 public void testIsRotationLockEnforced_statusBarVisible_lockNotEnforced() { 156 // Some system bars are visible 157 when(mMockWindowState.getRequestedVisibleTypes()).thenReturn(Type.statusBars()); 158 159 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 160 } 161 162 @Test testIsRotationLockEnforced_navBarVisible_lockNotEnforced()163 public void testIsRotationLockEnforced_navBarVisible_lockNotEnforced() { 164 // Some system bars are visible 165 when(mMockWindowState.getRequestedVisibleTypes()).thenReturn(Type.navigationBars()); 166 167 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 168 } 169 170 @Test testIsRotationLockEnforced_activityIsLetterboxed_lockNotEnforced()171 public void testIsRotationLockEnforced_activityIsLetterboxed_lockNotEnforced() { 172 // Activity is letterboxed 173 when(mMockActivityRecord.areBoundsLetterboxed()).thenReturn(true); 174 175 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 176 } 177 178 @Test testIsRotationLockEnforced_notFullscreen_lockNotEnforced()179 public void testIsRotationLockEnforced_notFullscreen_lockNotEnforced() { 180 when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_MULTI_WINDOW); 181 182 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 183 184 when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_PINNED); 185 186 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 187 188 when(mMockTask.getWindowingMode()).thenReturn(WINDOWING_MODE_FREEFORM); 189 190 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 191 } 192 193 @Test testIsRotationLockEnforced_ignoreOrientationRequestDisabled_lockNotEnforced()194 public void testIsRotationLockEnforced_ignoreOrientationRequestDisabled_lockNotEnforced() { 195 when(mDisplayContent.getIgnoreOrientationRequest()).thenReturn(false); 196 197 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 198 } 199 200 @Test testRotationChoiceEnforcedOnly_nullTopRunningActivity_lockNotEnforced()201 public void testRotationChoiceEnforcedOnly_nullTopRunningActivity_lockNotEnforced() { 202 when(mDisplayContent.topRunningActivity()).thenReturn(null); 203 204 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 205 } 206 207 @Test testRotationChoiceEnforcedOnly_featureFlagDisabled_lockNotEnforced()208 public void testRotationChoiceEnforcedOnly_featureFlagDisabled_lockNotEnforced() { 209 when(mMockLetterboxConfiguration.isDisplayRotationImmersiveAppCompatPolicyEnabled()) 210 .thenReturn(false); 211 212 assertIsRotationLockEnforcedReturnsFalseForAllRotations(); 213 } 214 assertIsRotationLockEnforcedReturnsFalseForAllRotations()215 private void assertIsRotationLockEnforcedReturnsFalseForAllRotations() { 216 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_0)); 217 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_90)); 218 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_180)); 219 assertFalse(mPolicy.isRotationLockEnforced(Surface.ROTATION_270)); 220 } 221 } 222