1 /* 2 * Copyright (C) 2021 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 android.server.wm.display; 18 19 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 20 import static android.content.pm.ActivityInfo.FORCE_RESIZE_APP; 21 import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS; 22 import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED; 23 import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO; 24 import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE; 25 import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE; 26 import static android.content.pm.ActivityInfo.OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS; 27 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; 28 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 29 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; 30 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; 31 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 32 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 33 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 34 import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS; 35 import static android.server.wm.allowdisplayorientationoverride.Components.ALLOW_DISPLAY_ORIENTATION_OVERRIDE_ACTIVITY; 36 import static android.server.wm.allowignoringorientationrequestwhenloopdetectedoptin.Components.ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_IN_ACTIVITY; 37 import static android.server.wm.allowignoringorientationrequestwhenloopdetectedoptout.Components.ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_OUT_ACTIVITY; 38 import static android.server.wm.allowignoringorientationrequestwhenloopdetectedunset.Components.ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_UNSET_ACTIVITY; 39 import static android.server.wm.allowminaspectratiooverrideoptin.Components.ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY; 40 import static android.server.wm.allowminaspectratiooverrideoptout.Components.ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_OUT_ACTIVITY; 41 import static android.server.wm.alloworientationoverride.Components.ALLOW_ORIENTATION_OVERRIDE_LANDSCAPE_ACTIVITY; 42 import static android.server.wm.alloworientationoverride.Components.ALLOW_ORIENTATION_OVERRIDE_RESPONSIVE_ACTIVITY; 43 import static android.server.wm.allowresizeableactivityoverridesoptin.Components.ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_IN_ACTIVITY; 44 import static android.server.wm.allowresizeableactivityoverridesoptout.Components.ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_OUT_ACTIVITY; 45 import static android.server.wm.allowsandboxingviewboundsapis.Components.ACTION_TEST_VIEW_SANDBOX_ALLOWED_PASSED; 46 import static android.server.wm.allowsandboxingviewboundsapis.Components.ACTION_TEST_VIEW_SANDBOX_NOT_ALLOWED_PASSED; 47 import static android.server.wm.allowsandboxingviewboundsapis.Components.TEST_VIEW_SANDBOX_ALLOWED_ACTIVITY; 48 import static android.server.wm.allowsandboxingviewboundsapis.Components.TEST_VIEW_SANDBOX_ALLOWED_TIMEOUT_MS; 49 import static android.server.wm.allowuseraspectratiofullscreenoverrideoptin.Components.ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE_OPT_IN_ACTIVITY; 50 import static android.server.wm.allowuseraspectratiofullscreenoverrideoptout.Components.ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE_OPT_OUT_ACTIVITY; 51 import static android.server.wm.allowuseraspectratiooverrideoptin.Components.ALLOW_USER_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY; 52 import static android.server.wm.allowuseraspectratiooverrideoptout.Components.ALLOW_USER_ASPECT_RATIO_OVERRIDE_OPT_OUT_ACTIVITY; 53 import static android.server.wm.enablefakefocusoptin.Components.ENABLE_FAKE_FOCUS_OPT_IN_LEFT_ACTIVITY; 54 import static android.server.wm.enablefakefocusoptin.Components.ENABLE_FAKE_FOCUS_OPT_IN_RIGHT_ACTIVITY; 55 import static android.server.wm.enablefakefocusoptout.Components.ENABLE_FAKE_FOCUS_OPT_OUT_LEFT_ACTIVITY; 56 import static android.server.wm.enablefakefocusoptout.Components.ENABLE_FAKE_FOCUS_OPT_OUT_RIGHT_ACTIVITY; 57 import static android.server.wm.ignorerequestedorientationoverrideoptin.Components.OPT_IN_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY; 58 import static android.server.wm.ignorerequestedorientationoverrideoptout.Components.OPT_OUT_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY; 59 import static android.server.wm.optoutsandboxingviewboundsapis.Components.ACTION_TEST_VIEW_SANDBOX_OPT_OUT_PASSED; 60 import static android.server.wm.optoutsandboxingviewboundsapis.Components.TEST_VIEW_SANDBOX_OPT_OUT_ACTIVITY; 61 import static android.server.wm.optoutsandboxingviewboundsapis.Components.TEST_VIEW_SANDBOX_OPT_OUT_TIMEOUT_MS; 62 import static android.server.wm.propertycameracompatallowforcerotation.Components.CAMERA_COMPAT_ALLOW_FORCE_ROTATION_ACTIVITY; 63 import static android.server.wm.propertycameracompatallowrefresh.Components.CAMERA_COMPAT_ALLOW_REFRESH_ACTIVITY; 64 import static android.server.wm.propertycameracompatenablerefreshviapauseoptin.Components.CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE_OPT_IN_ACTIVITY; 65 import static android.server.wm.propertycameracompatenablerefreshviapauseoptout.Components.CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE_OPT_OUT_ACTIVITY; 66 import static android.view.Surface.ROTATION_0; 67 import static android.view.Surface.ROTATION_90; 68 69 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; 70 71 import static com.google.common.truth.Truth.assertThat; 72 73 import static org.junit.Assert.assertEquals; 74 import static org.junit.Assert.assertFalse; 75 import static org.junit.Assert.assertNotNull; 76 import static org.junit.Assert.assertTrue; 77 import static org.junit.Assume.assumeFalse; 78 import static org.junit.Assume.assumeTrue; 79 80 import android.app.Activity; 81 import android.app.WindowConfiguration; 82 import android.compat.testing.PlatformCompatChangeRule; 83 import android.content.BroadcastReceiver; 84 import android.content.ComponentName; 85 import android.content.Context; 86 import android.content.Intent; 87 import android.content.IntentFilter; 88 import android.content.pm.ActivityInfo; 89 import android.content.pm.PackageManager; 90 import android.content.res.Resources; 91 import android.graphics.Rect; 92 import android.os.Bundle; 93 import android.os.ConditionVariable; 94 import android.platform.test.annotations.Presubmit; 95 import android.platform.test.annotations.RequiresFlagsEnabled; 96 import android.platform.test.flag.junit.CheckFlagsRule; 97 import android.platform.test.flag.junit.DeviceFlagsValueProvider; 98 import android.provider.DeviceConfig; 99 import android.server.wm.HelperActivities; 100 import android.server.wm.MultiDisplayTestBase; 101 import android.server.wm.WindowManagerState; 102 import android.server.wm.app.AbstractLifecycleLogActivity; 103 import android.util.Size; 104 105 import androidx.annotation.NonNull; 106 import androidx.annotation.Nullable; 107 108 import com.android.compatibility.common.util.ApiTest; 109 import com.android.window.flags.Flags; 110 111 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges; 112 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges; 113 114 import org.junit.Before; 115 import org.junit.Ignore; 116 import org.junit.Rule; 117 import org.junit.Test; 118 import org.junit.rules.TestRule; 119 120 import java.util.Collections; 121 import java.util.HashMap; 122 import java.util.Map; 123 124 /** 125 * The test is focused on compatibility changes that have an effect on WM logic, and tests that 126 * enabling these changes has the correct effect. 127 * 128 * This is achieved by launching a custom activity with certain properties (e.g., a resizeable 129 * portrait activity) that behaves in a certain way (e.g., enter size compat mode after resizing the 130 * display) and enabling a compatibility change (e.g., {@link ActivityInfo#FORCE_RESIZE_APP}) that 131 * changes that behavior (e.g., not enter size compat mode). 132 * 133 * The behavior without enabling a compatibility change is also tested as a baseline. 134 * 135 * <p>Build/Install/Run: 136 * atest CtsWindowManagerDeviceDisplay:CompatChangeTests 137 */ 138 @Presubmit 139 public final class CompatChangeTests extends MultiDisplayTestBase { 140 private static final ComponentName RESIZEABLE_PORTRAIT_ACTIVITY = 141 component(HelperActivities.ResizeablePortraitActivity.class); 142 private static final ComponentName NON_RESIZEABLE_PORTRAIT_ACTIVITY = 143 component(HelperActivities.NonResizeablePortraitActivity.class); 144 private static final ComponentName NON_RESIZEABLE_LANDSCAPE_ACTIVITY = 145 component(HelperActivities.NonResizeableLandscapeActivity.class); 146 private static final ComponentName NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY = 147 component(HelperActivities.NonResizeableNonFixedOrientationActivity.class); 148 private static final ComponentName NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY = 149 component(HelperActivities.NonResizeableAspectRatioActivity.class); 150 private static final ComponentName NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY = 151 component(HelperActivities.NonResizeableLargeAspectRatioActivity.class); 152 private static final ComponentName SUPPORTS_SIZE_CHANGES_PORTRAIT_ACTIVITY = 153 component(HelperActivities.SupportsSizeChangesPortraitActivity.class); 154 private static final ComponentName RESIZEABLE_LEFT_ACTIVITY = 155 component(HelperActivities.ResizeableLeftActivity.class); 156 private static final ComponentName RESIZEABLE_RIGHT_ACTIVITY = 157 component(HelperActivities.ResizeableRightActivity.class); 158 private static final ComponentName RESPONSIVE_ACTIVITY = 159 component(HelperActivities.ResponsiveActivity.class); 160 private static final ComponentName NO_PROPERTY_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY = 161 component(HelperActivities.NoPropertyChangeOrientationWhileRelaunchingActivity.class); 162 163 // Fixed orientation min aspect ratio 164 private static final float FIXED_ORIENTATION_MIN_ASPECT_RATIO = 1.03f; 165 // The min aspect ratio of NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY (as defined in the manifest). 166 private static final float ACTIVITY_MIN_ASPECT_RATIO = 1.6f; 167 // The min aspect ratio of NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY (as defined in the 168 // manifest). This needs to be higher than the aspect ratio of any device, which according to 169 // CDD is at most 21:9. 170 private static final float ACTIVITY_LARGE_MIN_ASPECT_RATIO = 4f; 171 172 private static final float FLOAT_EQUALITY_DELTA = 0.01f; 173 174 @Rule 175 public TestRule compatChangeRule = new PlatformCompatChangeRule(); 176 @Rule 177 public final CheckFlagsRule checkFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); 178 179 @Before 180 @Override setUp()181 public void setUp() throws Exception { 182 super.setUp(); 183 enableAndAssumeGestureNavigationMode(); 184 createManagedLetterboxAspectRatioSession(FIXED_ORIENTATION_MIN_ASPECT_RATIO); 185 mObjectTracker.manage(setAlwaysConstrainDisplayApisFlag(null)); 186 mObjectTracker.manage(setNeverConstrainDisplayApisAllPackagesFlag(null)); 187 mObjectTracker.manage(setNeverConstrainDisplayApisFlag(null)); 188 } 189 190 @Test testOverrideUndefinedOrientationToPortrait_propertyIsFalse_overrideNotApplied()191 public void testOverrideUndefinedOrientationToPortrait_propertyIsFalse_overrideNotApplied() { 192 try (var compatChange = new CompatChangeCloseable( 193 ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT, 194 ALLOW_ORIENTATION_OVERRIDE_RESPONSIVE_ACTIVITY.getPackageName()); 195 var session = new ActivitySessionCloseable( 196 ALLOW_ORIENTATION_OVERRIDE_RESPONSIVE_ACTIVITY)) { 197 waitAssertEquals("expected unspecified orientation", 198 SCREEN_ORIENTATION_UNSPECIFIED, 199 () -> session.getActivityState().getOverrideOrientation()); 200 } 201 } 202 203 @Test 204 @EnableCompatChanges({ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_PORTRAIT}) testOverrideUndefinedOrientationToPortrait()205 public void testOverrideUndefinedOrientationToPortrait() { 206 try (var session = new ActivitySessionCloseable(RESPONSIVE_ACTIVITY)) { 207 waitAssertEquals("expected portrait orientation", SCREEN_ORIENTATION_PORTRAIT, 208 () -> session.getActivityState().getOverrideOrientation()); 209 } 210 } 211 212 @Test testOverrideUndefinedOrientationToNoSensor_propertyIsFalse_overrideNotApplied()213 public void testOverrideUndefinedOrientationToNoSensor_propertyIsFalse_overrideNotApplied() { 214 try (var compatChange = new CompatChangeCloseable( 215 ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR, 216 ALLOW_ORIENTATION_OVERRIDE_RESPONSIVE_ACTIVITY.getPackageName()); 217 var session = new ActivitySessionCloseable( 218 ALLOW_ORIENTATION_OVERRIDE_RESPONSIVE_ACTIVITY)) { 219 waitAssertEquals("expected unspecified orientation", 220 SCREEN_ORIENTATION_UNSPECIFIED, 221 () -> session.getActivityState().getOverrideOrientation()); 222 } 223 } 224 225 @Test 226 @EnableCompatChanges({ActivityInfo.OVERRIDE_UNDEFINED_ORIENTATION_TO_NOSENSOR}) testOverrideUndefinedOrientationToNosensor()227 public void testOverrideUndefinedOrientationToNosensor() { 228 try (var session = new ActivitySessionCloseable(RESPONSIVE_ACTIVITY)) { 229 waitAssertEquals("expected no-sensor orientation", 230 SCREEN_ORIENTATION_NOSENSOR, 231 () -> session.getActivityState().getOverrideOrientation()); 232 } 233 } 234 235 @Test 236 public void testOverrideLandscapeOrientationToReverseLandscape_propertyIsFalse_overrideNotApply()237 testOverrideLandscapeOrientationToReverseLandscape_propertyIsFalse_overrideNotApply() { 238 try (var compatChange = new CompatChangeCloseable( 239 ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE, 240 ALLOW_ORIENTATION_OVERRIDE_LANDSCAPE_ACTIVITY.getPackageName()); 241 var session = new ActivitySessionCloseable( 242 ALLOW_ORIENTATION_OVERRIDE_LANDSCAPE_ACTIVITY)) { 243 waitAssertEquals("expected landscape orientation", SCREEN_ORIENTATION_LANDSCAPE, 244 () -> session.getActivityState().getOverrideOrientation()); 245 } 246 } 247 248 @Test 249 @EnableCompatChanges({ActivityInfo.OVERRIDE_LANDSCAPE_ORIENTATION_TO_REVERSE_LANDSCAPE}) testOverrideLandscapeOrientationToReverseLandscape()250 public void testOverrideLandscapeOrientationToReverseLandscape() { 251 try (var session = new ActivitySessionCloseable(NON_RESIZEABLE_LANDSCAPE_ACTIVITY)) { 252 waitAssertEquals("expected reverse landscape orientation", 253 SCREEN_ORIENTATION_REVERSE_LANDSCAPE, 254 () -> session.getActivityState().getOverrideOrientation()); 255 } 256 } 257 258 @Test 259 @EnableCompatChanges({ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION}) testOverrideUseDisplayLandscapeNaturalOrientation()260 public void testOverrideUseDisplayLandscapeNaturalOrientation() { 261 try (var displayMetricsSession = new DisplayMetricsWaitCloseable()) { 262 // Run this test only when natural orientation is landscape 263 Size displaySize = displayMetricsSession.getInitialDisplayMetrics().getSize(); 264 assumeTrue(displaySize.getHeight() < displaySize.getWidth()); 265 } 266 267 try (var portrait = new DeviceOrientationCloseable(ORIENTATION_PORTRAIT); 268 var session = new ActivitySessionCloseable(RESPONSIVE_ACTIVITY)) { 269 // Verifying that orientation is overridden 270 waitAssertEquals("expected rotation 0", 271 ROTATION_0, () -> mWmState.getRotation()); 272 } 273 } 274 275 @Test 276 public void testOverrideUseDisplayLandscapeNaturalOrientation_propertyIsFalse_overrideNotApplied()277 testOverrideUseDisplayLandscapeNaturalOrientation_propertyIsFalse_overrideNotApplied() { 278 try (var displayMetricsSession = new DisplayMetricsWaitCloseable()) { 279 // Run this test only when natural orientation is landscape 280 Size displaySize = displayMetricsSession.getInitialDisplayMetrics().getSize(); 281 assumeTrue(displaySize.getHeight() < displaySize.getWidth()); 282 } 283 284 final int originalRotation = mWmState.getRotation(); 285 286 try (var portrait = new DeviceOrientationCloseable(ORIENTATION_PORTRAIT); 287 var compatChange = new CompatChangeCloseable( 288 ActivityInfo.OVERRIDE_USE_DISPLAY_LANDSCAPE_NATURAL_ORIENTATION, 289 ALLOW_DISPLAY_ORIENTATION_OVERRIDE_ACTIVITY.getPackageName()); 290 var session = new ActivitySessionCloseable( 291 ALLOW_DISPLAY_ORIENTATION_OVERRIDE_ACTIVITY)) { 292 293 // Verifying that orientation not overridden 294 if (portrait.isRotationApplied()) { 295 // If the screen was rotated away from natural orientation (to portrait) 296 waitAssertEquals("expected rotation 90", 297 ROTATION_90, () -> mWmState.getRotation()); 298 } else { 299 // If the screen was already in portrait (rotated away from natural orientation) 300 waitAssertEquals("expected originalRotation=" + originalRotation, 301 originalRotation, () -> mWmState.getRotation()); 302 } 303 } 304 } 305 306 @Test testEnableFakeFocus_propertyIsFalse_overrideNotApplied()307 public void testEnableFakeFocus_propertyIsFalse_overrideNotApplied() { 308 assumeTrue("Skipping test: no split multi-window support", 309 supportsSplitScreenMultiWindow()); 310 assumeTrue("Skipping test: config_isCompatFakeFocusEnabled not enabled", 311 getFakeFocusEnabledConfig()); 312 313 try (var compatChange = new CompatChangeCloseable( 314 OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS, 315 ENABLE_FAKE_FOCUS_OPT_OUT_LEFT_ACTIVITY.getPackageName()); 316 var splitScreen = new SplitScreenActivitiesCloseable( 317 ENABLE_FAKE_FOCUS_OPT_OUT_LEFT_ACTIVITY, 318 ENABLE_FAKE_FOCUS_OPT_OUT_RIGHT_ACTIVITY)) { 319 waitAssertEquals("expected should not send compat fake focus", 320 /* expected */ false, 321 () -> splitScreen.getPrimaryActivity() 322 .getActivityState().getShouldSendCompatFakeFocus()); 323 } 324 } 325 326 @Test testEnableFakeFocus_propertyIsTrue_returnsTrue()327 public void testEnableFakeFocus_propertyIsTrue_returnsTrue() { 328 assumeTrue("Skipping test: no split multi-window support", 329 supportsSplitScreenMultiWindow()); 330 assumeTrue("Skipping test: config_isCompatFakeFocusEnabled not enabled", 331 getFakeFocusEnabledConfig()); 332 333 try (var splitScreen = new SplitScreenActivitiesCloseable( 334 ENABLE_FAKE_FOCUS_OPT_IN_LEFT_ACTIVITY, 335 ENABLE_FAKE_FOCUS_OPT_IN_RIGHT_ACTIVITY)) { 336 waitAssertEquals("expected should send compat fake focus", /* expected */ true, 337 () -> splitScreen.getPrimaryActivity() 338 .getActivityState().getShouldSendCompatFakeFocus()); 339 } 340 } 341 342 @Test 343 @EnableCompatChanges({OVERRIDE_ENABLE_COMPAT_FAKE_FOCUS}) testEnableFakeFocus_overrideApplied_returnsTrue()344 public void testEnableFakeFocus_overrideApplied_returnsTrue() { 345 assumeTrue("Skipping test: no split multi-window support", 346 supportsSplitScreenMultiWindow()); 347 assumeTrue("Skipping test: config_isCompatFakeFocusEnabled not enabled", 348 getFakeFocusEnabledConfig()); 349 350 try (var splitScreen = new SplitScreenActivitiesCloseable( 351 RESIZEABLE_LEFT_ACTIVITY, 352 RESIZEABLE_RIGHT_ACTIVITY)) { 353 waitAssertEquals("expected should send compat fake focus", /* expected */ true, 354 () -> splitScreen.getPrimaryActivity() 355 .getActivityState().getShouldSendCompatFakeFocus()); 356 } 357 } 358 getFakeFocusEnabledConfig()359 boolean getFakeFocusEnabledConfig() { 360 return mContext.getResources().getBoolean( 361 Resources.getSystem().getIdentifier( 362 "config_isCompatFakeFocusEnabled", 363 "bool", "android")); 364 } 365 366 @Test 367 @Ignore("b/295873734 flaky") testOverrideIgnoreRequestedOrientation_propertyIsFalse_overrideNotApplied()368 public void testOverrideIgnoreRequestedOrientation_propertyIsFalse_overrideNotApplied() { 369 assumeTrue("Skipping test: " 370 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled not enabled", 371 isPolicyForIgnoringRequestedOrientationEnabled()); 372 373 try (var compatChange = new CompatChangeCloseable( 374 ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION, 375 OPT_OUT_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY.getPackageName()); 376 var session = new ActivitySessionCloseable( 377 OPT_OUT_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY)) { 378 waitAssertEquals("expected landscape orientation", 379 SCREEN_ORIENTATION_LANDSCAPE, 380 () -> session.getActivityState().getOverrideOrientation()); 381 } 382 } 383 384 @Test testOverrideIgnoreRequestedOrientation_isDisabled_propertyIsTrue_overrideApplied()385 public void testOverrideIgnoreRequestedOrientation_isDisabled_propertyIsTrue_overrideApplied() { 386 assumeTrue("Skipping test: " 387 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled not enabled", 388 isPolicyForIgnoringRequestedOrientationEnabled()); 389 390 try (var session = new ActivitySessionCloseable( 391 OPT_IN_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY)) { 392 waitAssertEquals("expected portrait orientation", 393 SCREEN_ORIENTATION_PORTRAIT, 394 () -> session.getActivityState().getOverrideOrientation()); 395 } 396 } 397 398 @Test 399 @EnableCompatChanges({ActivityInfo.OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION}) testOverrideIgnoreRequestedOrientation()400 public void testOverrideIgnoreRequestedOrientation() { 401 assumeTrue("Skipping test: " 402 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled not enabled", 403 isPolicyForIgnoringRequestedOrientationEnabled()); 404 405 try (var session = new ActivitySessionCloseable( 406 NO_PROPERTY_CHANGE_ORIENTATION_WHILE_RELAUNCHING_ACTIVITY)) { 407 waitAssertEquals("expected portrait orientation", 408 SCREEN_ORIENTATION_PORTRAIT, 409 () -> session.getActivityState().getOverrideOrientation()); 410 } 411 } 412 413 /** 414 * Test that if an orientation loop is detected, the orientation request is ignored when 415 * {@link ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} is 416 * enabled and {@link 417 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} 418 * is set to true. 419 */ 420 @Test 421 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 422 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"}) 423 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyTrue_overrideEnabled_overrideApplied()424 public void testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyTrue_overrideEnabled_overrideApplied() { 425 assumeTrue("Skipping test: " 426 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled disabled", 427 isPolicyForIgnoringRequestedOrientationEnabled()); 428 429 try (var compatChange = new CompatChangeCloseable( 430 OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED, 431 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_IN_ACTIVITY 432 .getPackageName()); 433 var session = new ActivitySessionCloseable( 434 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_IN_ACTIVITY)) { 435 // Activity with property set to true and override enabled. Orientation request should 436 // be ignored if a loop is detected. 437 assertTrue(session.getActivityState().getShouldIgnoreOrientationRequestLoop()); 438 } 439 } 440 441 /** 442 * Test that if an orientation loop is detected, the orientation request is respected when 443 * {@link ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} is 444 * enabled but {@link 445 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} 446 * is set to false. 447 */ 448 @Test 449 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 450 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"}) 451 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyFalse_overrideEnabled_overrideNotApplied()452 public void testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyFalse_overrideEnabled_overrideNotApplied() { 453 assumeTrue("Skipping test: " 454 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled disabled", 455 isPolicyForIgnoringRequestedOrientationEnabled()); 456 457 try (var compatChange = new CompatChangeCloseable( 458 OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED, 459 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_OUT_ACTIVITY 460 .getPackageName()); 461 var session = new ActivitySessionCloseable( 462 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_OUT_ACTIVITY)) { 463 // Activity with property set to false and override enabled. Orientation request should 464 // be respected even if a loop is detected. 465 assertFalse(session.getActivityState().getShouldIgnoreOrientationRequestLoop()); 466 467 468 } 469 } 470 471 /** 472 * Test that if an orientation loop is detected, the orientation request is respected when 473 * {@link ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} is 474 * disabled but {@link 475 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} 476 * is set to true. 477 */ 478 @Test 479 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 480 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"}) 481 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyTrue_overrideDisabled_overrideNotApplied()482 public void testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyTrue_overrideDisabled_overrideNotApplied() { 483 assumeTrue("Skipping test: " 484 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled disabled", 485 isPolicyForIgnoringRequestedOrientationEnabled()); 486 487 try (var session = new ActivitySessionCloseable( 488 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_IN_ACTIVITY)) { 489 // Activity with property set to true but with override disabled. Orientation request 490 // should be respected even if a loop is detected. 491 assertFalse(session.getActivityState().getShouldIgnoreOrientationRequestLoop()); 492 } 493 } 494 495 /** 496 * Test that if an orientation loop is detected, the orientation request is respected when 497 * {@link ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} is 498 * disabled and {@link 499 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} 500 * is set to false. 501 */ 502 @Test 503 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 504 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"}) 505 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyFalse_overrideDisabled_overrideNotApplied()506 public void testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyFalse_overrideDisabled_overrideNotApplied() { 507 assumeTrue("Skipping test: " 508 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled disabled", 509 isPolicyForIgnoringRequestedOrientationEnabled()); 510 511 try (var session = new ActivitySessionCloseable( 512 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_OPT_OUT_ACTIVITY)) { 513 // Activity with property set to false and with override disabled. Orientation request 514 // should be respected even if a loop is detected. 515 assertFalse(session.getActivityState().getShouldIgnoreOrientationRequestLoop()); 516 } 517 } 518 519 /** 520 * Test that if an orientation loop is detected, the orientation request is ignored when 521 * {@link ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} is 522 * enabled and {@link 523 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} 524 * is unset. 525 */ 526 @Test 527 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 528 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"}) 529 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyNotSet_overrideEnabled_overrideApplied()530 public void testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyNotSet_overrideEnabled_overrideApplied() { 531 assumeTrue("Skipping test: " 532 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled disabled", 533 isPolicyForIgnoringRequestedOrientationEnabled()); 534 535 try (var compatChange = new CompatChangeCloseable( 536 OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED, 537 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_UNSET_ACTIVITY 538 .getPackageName()); 539 var session = new ActivitySessionCloseable( 540 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_UNSET_ACTIVITY)) { 541 // Activity without property set and override enabled. Property will default to true. 542 // Orientation request should be ignored if a loop is detected. 543 assertTrue(session.getActivityState().getShouldIgnoreOrientationRequestLoop()); 544 } 545 } 546 547 /** 548 * Test that if an orientation loop is detected, the orientation request is respected when 549 * {@link ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} is 550 * disabled and {@link 551 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED} 552 * is unset. 553 */ 554 @Test 555 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_ENABLE_COMPAT_IGNORE_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED", 556 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED"}) 557 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyNotSet_overrideDisabled_overrideNotApplied()558 public void testOverrideIgnoreOrientationRequestWhenLoopDetected_propertyNotSet_overrideDisabled_overrideNotApplied() { 559 assumeTrue("Skipping test: " 560 + "config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled disabled", 561 isPolicyForIgnoringRequestedOrientationEnabled()); 562 563 try (var session = new ActivitySessionCloseable( 564 ALLOW_IGNORING_ORIENTATION_REQUEST_WHEN_LOOP_DETECTED_UNSET_ACTIVITY)) { 565 // Activity without property set and with override disabled. Orientation request should 566 // be respected even if a loop is detected. 567 assertFalse(session.getActivityState().getShouldIgnoreOrientationRequestLoop()); 568 } 569 } 570 571 572 @Test testOptOutPropertyCameraCompatForceRotation_rotationDisabled()573 public void testOptOutPropertyCameraCompatForceRotation_rotationDisabled() { 574 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 575 isCameraCompatForceRotationTreatmentConfigEnabled()); 576 577 try (var session = new ActivitySessionCloseable(RESIZEABLE_PORTRAIT_ACTIVITY)) { 578 // Activity without property or override is eligible for force rotation. 579 waitAssertEquals("expected to force rotate for camera compat", 580 /* expected */ true, 581 () -> session.getActivityState().getShouldForceRotateForCameraCompat()); 582 } 583 584 try (var session = new ActivitySessionCloseable( 585 CAMERA_COMPAT_ALLOW_FORCE_ROTATION_ACTIVITY)) { 586 waitAssertEquals("expected to not force rotate for camera compat", 587 /* expected */ false, 588 () -> session.getActivityState().getShouldForceRotateForCameraCompat()); 589 } 590 } 591 592 @Test 593 @EnableCompatChanges({ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_FORCE_ROTATION}) testOverrideForCameraCompatForceRotation_rotationDisabled()594 public void testOverrideForCameraCompatForceRotation_rotationDisabled() { 595 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 596 isCameraCompatForceRotationTreatmentConfigEnabled()); 597 598 try (var session = new ActivitySessionCloseable(RESIZEABLE_PORTRAIT_ACTIVITY)) { 599 waitAssertEquals("expected to not force rotate for camera compat", 600 /* expected */ false, 601 () -> session.getActivityState().getShouldForceRotateForCameraCompat()); 602 } 603 } 604 605 @Test testOptOutPropertyCameraCompatRefresh()606 public void testOptOutPropertyCameraCompatRefresh() { 607 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 608 isCameraCompatForceRotationTreatmentConfigEnabled()); 609 610 try (var session = new ActivitySessionCloseable(RESIZEABLE_PORTRAIT_ACTIVITY)) { 611 // Activity without property or override is eligible for refresh. 612 waitAssertEquals("expected to refresh activity for camera compat", 613 /* expected */ true, 614 () -> session.getActivityState().getShouldRefreshActivityForCameraCompat()); 615 } 616 617 try (var session = new ActivitySessionCloseable(CAMERA_COMPAT_ALLOW_REFRESH_ACTIVITY)) { 618 waitAssertEquals("expected to not refresh activity for camera compat", 619 /* expected */ false, 620 () -> session.getActivityState().getShouldRefreshActivityForCameraCompat()); 621 } 622 } 623 624 @Test 625 @EnableCompatChanges({ActivityInfo.OVERRIDE_CAMERA_COMPAT_DISABLE_REFRESH}) testOverrideForCameraCompatRefresh()626 public void testOverrideForCameraCompatRefresh() { 627 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 628 isCameraCompatForceRotationTreatmentConfigEnabled()); 629 630 try (var session = new ActivitySessionCloseable(RESIZEABLE_PORTRAIT_ACTIVITY)) { 631 waitAssertEquals("expected to not refresh activity for camera compat", 632 /* expected */ false, 633 () -> session.getActivityState().getShouldRefreshActivityForCameraCompat()); 634 } 635 } 636 637 @Test testOptInPropertyCameraCompatRefreshViaPause()638 public void testOptInPropertyCameraCompatRefreshViaPause() { 639 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 640 isCameraCompatForceRotationTreatmentConfigEnabled()); 641 642 try (var session = new ActivitySessionCloseable(RESIZEABLE_PORTRAIT_ACTIVITY)) { 643 // Activity without property or override doesn't refresh via 644 // "resumed -> paused -> resumed". 645 waitAssertEquals("expected to not refresh activity via pause for camera compat", 646 /* expected */ false, 647 () -> session.getActivityState() 648 .getShouldRefreshActivityViaPauseForCameraCompat()); 649 } 650 651 try (var session = new ActivitySessionCloseable( 652 CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE_OPT_IN_ACTIVITY)) { 653 waitAssertEquals("expected to Refresh activity via pause for camera compat", 654 /* expected */ true, 655 () -> session.getActivityState() 656 .getShouldRefreshActivityViaPauseForCameraCompat()); 657 } 658 } 659 660 @Test 661 @EnableCompatChanges({ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE}) testOverrideForCameraCompatRefreshViaPause()662 public void testOverrideForCameraCompatRefreshViaPause() { 663 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 664 isCameraCompatForceRotationTreatmentConfigEnabled()); 665 666 try (var session = new ActivitySessionCloseable(RESIZEABLE_PORTRAIT_ACTIVITY)) { 667 waitAssertEquals("expected to Refresh activity via pause for camera compat", 668 /* expected */ true, 669 () -> session.getActivityState() 670 .getShouldRefreshActivityViaPauseForCameraCompat()); 671 } 672 } 673 674 @Test testOptOutPropertyCameraCompatRefreshViaPause()675 public void testOptOutPropertyCameraCompatRefreshViaPause() { 676 assumeTrue("Skipping test: config_isWindowManagerCameraCompatTreatmentEnabled not enabled", 677 isCameraCompatForceRotationTreatmentConfigEnabled()); 678 679 try (var compatChange = new CompatChangeCloseable( 680 ActivityInfo.OVERRIDE_CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE, 681 CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE_OPT_OUT_ACTIVITY.getPackageName()); 682 var session = new ActivitySessionCloseable( 683 CAMERA_COMPAT_ENABLE_REFRESH_VIA_PAUSE_OPT_OUT_ACTIVITY)) { 684 waitAssertEquals("expected to not refresh activity via pause for camera compat", 685 /* expected */ false, 686 () -> session.getActivityState() 687 .getShouldRefreshActivityViaPauseForCameraCompat()); 688 } 689 } 690 691 /** 692 * Test that an activity is forced to be resizeable when {@link 693 * ActivityInfo#FORCE_RESIZE_APP} is enabled and {@link 694 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES} is set to 695 * true. 696 */ 697 @Test 698 @ApiTest(apis = {"android.content.pm.ActivityInfo#FORCE_RESIZE_APP", 699 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"}) 700 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideForceResizeApp_propertyTrue_overrideEnabled_overrideApplied()701 public void testOverrideForceResizeApp_propertyTrue_overrideEnabled_overrideApplied() { 702 try (var compatChange = new CompatChangeCloseable( 703 FORCE_RESIZE_APP, 704 ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_IN_ACTIVITY.getPackageName()); 705 var session = new ActivitySessionCloseable( 706 ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_IN_ACTIVITY)) { 707 // Activity with property set to true and override enabled. Activity should be forced to 708 // be resizeable. 709 assertTrue(session.getActivityState().getShouldOverrideForceResizeApp()); 710 } 711 } 712 713 /** 714 * Test that an activity is not forced to be resizeable when {@link 715 * ActivityInfo#FORCE_RESIZE_APP} is enabled but {@link 716 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES} is set to 717 * false. 718 */ 719 @Test 720 @ApiTest(apis = {"android.content.pm.ActivityInfo#FORCE_RESIZE_APP", 721 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"}) 722 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideForceResizeApp_propertyFalse_overrideEnabled_overrideNotApplied()723 public void testOverrideForceResizeApp_propertyFalse_overrideEnabled_overrideNotApplied() { 724 try (var compatChange = new CompatChangeCloseable( 725 FORCE_RESIZE_APP, 726 ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_OUT_ACTIVITY.getPackageName()); 727 var session = new ActivitySessionCloseable( 728 ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_OUT_ACTIVITY)) { 729 // Activity with property set to false and override enabled. Activity should not be 730 // forced to be resizeable. 731 assertFalse(session.getActivityState().getShouldOverrideForceResizeApp()); 732 } 733 } 734 735 /** 736 * Test that an activity is not forced to be resizeable when {@link 737 * ActivityInfo#FORCE_RESIZE_APP} is disabled but {@link 738 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES} is set to 739 * true. 740 */ 741 @Test 742 @ApiTest(apis = {"android.content.pm.ActivityInfo#FORCE_RESIZE_APP", 743 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"}) 744 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideForceResizeApp_propertyTrue_overrideDisabled_overrideNotApplied()745 public void testOverrideForceResizeApp_propertyTrue_overrideDisabled_overrideNotApplied() { 746 try (var session = new ActivitySessionCloseable( 747 ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_IN_ACTIVITY)) { 748 // Activity with property set to true and override disabled. Activity should not be 749 // forced to be resizeable. 750 assertFalse(session.getActivityState().getShouldOverrideForceResizeApp()); 751 } 752 } 753 754 /** 755 * Test that an activity is not forced to be resizeable when {@link 756 * ActivityInfo#FORCE_RESIZE_APP} is disabled and {@link 757 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES} is set to 758 * false. 759 */ 760 @Test 761 @ApiTest(apis = {"android.content.pm.ActivityInfo#FORCE_RESIZE_APP", 762 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"}) 763 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideForceResizeApp_propertyFalse_overrideDisabled_overrideApplied()764 public void testOverrideForceResizeApp_propertyFalse_overrideDisabled_overrideApplied() { 765 try (var session = new ActivitySessionCloseable( 766 ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES_OPT_OUT_ACTIVITY)) { 767 // Activity with property set to false and override disabled. Activity should not be 768 // forced to be resizeable. 769 assertFalse(session.getActivityState().getShouldOverrideForceResizeApp()); 770 } 771 } 772 773 /** 774 * Test that an activity is forced to be resizeable when {@link 775 * ActivityInfo#FORCE_RESIZE_APP} is enabled and {@link 776 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES} is unset. 777 */ 778 @Test 779 @ApiTest(apis = {"android.content.pm.ActivityInfo#FORCE_RESIZE_APP", 780 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"}) 781 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 782 @EnableCompatChanges({ActivityInfo.FORCE_RESIZE_APP}) testOverrideForceResizeApp_propertyUnset_overrideEnabled_overrideApplied()783 public void testOverrideForceResizeApp_propertyUnset_overrideEnabled_overrideApplied() { 784 try (var session = new ActivitySessionCloseable( 785 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 786 // Activity with property unset and override enabled. Property will default to true. 787 // Activity should be forced to be resizeable. 788 assertTrue(session.getActivityState().getShouldOverrideForceResizeApp()); 789 } 790 } 791 792 /** 793 * Test that an activity is not forced to be resizeable when {@link 794 * ActivityInfo#FORCE_RESIZE_APP} is disabled and {@link 795 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES} is unset. 796 */ 797 @Test 798 @ApiTest(apis = {"android.content.pm.ActivityInfo#FORCE_RESIZE_APP", 799 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_RESIZEABLE_ACTIVITY_OVERRIDES"}) 800 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 801 @DisableCompatChanges({ActivityInfo.FORCE_RESIZE_APP}) testOverrideForceResizeApp_propertyUnset_overrideDisabled_overrideNotApplied()802 public void testOverrideForceResizeApp_propertyUnset_overrideDisabled_overrideNotApplied() { 803 try (var session = new ActivitySessionCloseable( 804 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 805 // Activity with property unset and override disabled. Activity should not be forced to 806 // be resizeable. 807 assertFalse(session.getActivityState().getShouldOverrideForceResizeApp()); 808 } 809 } 810 811 /** 812 * Test that a non-resizeable portrait activity enters size compat mode after resizing the 813 * display. 814 */ 815 @Test testSizeCompatForNonResizeableActivity()816 public void testSizeCompatForNonResizeableActivity() { 817 runSizeCompatTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* inSizeCompatModeAfterResize */ true); 818 } 819 820 /** 821 * Test that a non-resizeable portrait activity doesn't enter size compat mode after resizing 822 * the display, when the {@link ActivityInfo#FORCE_RESIZE_APP} compat change is enabled. 823 */ 824 @Test 825 @EnableCompatChanges({ActivityInfo.FORCE_RESIZE_APP}) testSizeCompatForNonResizeableActivityForceResizeEnabled()826 public void testSizeCompatForNonResizeableActivityForceResizeEnabled() { 827 runSizeCompatTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /*inSizeCompatModeAfterResize */ false); 828 } 829 830 /** 831 * Test that a resizeable portrait activity doesn't enter size compat mode after resizing 832 * the display. 833 */ 834 @Test testSizeCompatForResizeableActivity()835 public void testSizeCompatForResizeableActivity() { 836 runSizeCompatTest(RESIZEABLE_PORTRAIT_ACTIVITY, /* inSizeCompatModeAfterResize */ false); 837 } 838 839 /** 840 * Test that a non-resizeable portrait activity that supports size changes doesn't enter size 841 * compat mode after resizing the display. 842 */ 843 @Test testSizeCompatForSupportsSizeChangesActivity()844 public void testSizeCompatForSupportsSizeChangesActivity() { 845 runSizeCompatTest( 846 SUPPORTS_SIZE_CHANGES_PORTRAIT_ACTIVITY, /* inSizeCompatModeAfterResize */ false); 847 } 848 849 /** 850 * Test that a resizeable portrait activity enters size compat mode after resizing 851 * the display, when the {@link ActivityInfo#FORCE_NON_RESIZE_APP} compat change is enabled. 852 */ 853 @Test 854 @EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP}) testSizeCompatForResizeableActivityForceNonResizeEnabled()855 public void testSizeCompatForResizeableActivityForceNonResizeEnabled() { 856 runSizeCompatTest(RESIZEABLE_PORTRAIT_ACTIVITY, /* inSizeCompatModeAfterResize */ true); 857 } 858 859 /** 860 * Test that a non-resizeable portrait activity that supports size changes enters size compat 861 * mode after resizing the display, when the {@link ActivityInfo#FORCE_NON_RESIZE_APP} compat 862 * change is enabled. 863 */ 864 @Test 865 @EnableCompatChanges({ActivityInfo.FORCE_NON_RESIZE_APP}) testSizeCompatForSupportsSizeChangesActivityForceNonResizeEnabled()866 public void testSizeCompatForSupportsSizeChangesActivityForceNonResizeEnabled() { 867 runSizeCompatTest( 868 SUPPORTS_SIZE_CHANGES_PORTRAIT_ACTIVITY, /* inSizeCompatModeAfterResize */ true); 869 } 870 871 /** 872 * Test that a min aspect ratio activity eligible for size compat mode results in sandboxed 873 * Display APIs. 874 */ 875 @Test testSandboxForNonResizableAspectRatioActivity()876 public void testSandboxForNonResizableAspectRatioActivity() { 877 runSizeCompatModeSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, 878 /* isSandboxed */ true, /* inSizeCompatModeAfterResize */ true); 879 } 880 881 // ================= 882 // NEVER_SANDBOX test cases 883 // ================= 884 // Validates that an activity forced into size compat mode never has sandboxing applied to the 885 // max bounds. It is expected that an activity in size compat mode normally always has 886 // sandboxing applied. 887 888 /** 889 * Test that a min aspect ratio activity eligible for size compat mode does not have the Display 890 * APIs sandboxed when the {@link ActivityInfo#NEVER_SANDBOX_DISPLAY_APIS} compat change is 891 * enabled. 892 */ 893 @Test 894 @EnableCompatChanges({ActivityInfo.NEVER_SANDBOX_DISPLAY_APIS}) testSandboxForNonResizableAspectRatioActivityNeverSandboxDisplayApisEnabled()895 public void testSandboxForNonResizableAspectRatioActivityNeverSandboxDisplayApisEnabled() { 896 runSizeCompatModeSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, 897 /* isSandboxed */ false, /* inSizeCompatModeAfterResize */ true); 898 } 899 900 /** 901 * Test that a min aspect ratio activity eligible for size compat mode does not have the 902 * Display APIs sandboxed when the 'never_constrain_display_apis_all_packages' Device Config 903 * flag is true. 904 */ 905 @Test testSandboxForNonResizableActivityNeverSandboxDeviceConfigAllPackagesFlagTrue()906 public void testSandboxForNonResizableActivityNeverSandboxDeviceConfigAllPackagesFlagTrue() { 907 try (var neverForAll = setNeverConstrainDisplayApisAllPackagesFlag("true"); 908 var neverAnApp = setNeverConstrainDisplayApisFlag("com.android.other::")) { 909 runSizeCompatModeSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, 910 /* isSandboxed */ false, /* inSizeCompatModeAfterResize */ true); 911 } 912 } 913 914 /** 915 * Test that a min aspect ratio activity eligible for size compat mode does not have the Display 916 * APIs sandboxed when the 'never_constrain_display_apis' Device Config flag contains the test 917 * package with an open ended range. 918 */ 919 @Test testSandboxForNonResizableActivityPackageUnboundedInNeverSandboxDeviceConfigFlag()920 public void testSandboxForNonResizableActivityPackageUnboundedInNeverSandboxDeviceConfigFlag() { 921 ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY; 922 try (var neverForApp = setNeverConstrainDisplayApisFlag( 923 "com.android.other::," + activity.getPackageName() + "::")) { 924 runSizeCompatModeSandboxTest(activity, /* isSandboxed */ false, 925 /* inSizeCompatModeAfterResize */ true); 926 } 927 } 928 929 /** 930 * Test that a min aspect ratio activity eligible for size compat mode does not have the Display 931 * APIs sandboxed when the 'never_constrain_display_apis' Device Config flag contains the test 932 * package with a version range that matches the installed version of the package. 933 */ 934 @Test testSandboxForNonResizableActivityPackageWithinRangeInNeverSandboxDeviceConfig()935 public void testSandboxForNonResizableActivityPackageWithinRangeInNeverSandboxDeviceConfig() { 936 ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY; 937 long version = getPackageVersion(activity); 938 try (var neverForApp = setNeverConstrainDisplayApisFlag( 939 "com.android.other::," + activity.getPackageName() + ":" + String.valueOf( 940 version - 1) + ":" + String.valueOf(version + 1))) { 941 runSizeCompatModeSandboxTest(activity, /* isSandboxed */ false, 942 /* inSizeCompatModeAfterResize */ true); 943 } 944 } 945 946 /** 947 * Test that a min aspect ratio activity eligible for size compat mode does have the Display 948 * APIs sandboxed when the 'never_constrain_display_apis' Device Config flag contains the test 949 * package with a version range that doesn't match the installed version of the package. 950 */ 951 @Test testSandboxForNonResizableActivityPackageOutsideRangeInNeverSandboxDeviceConfig()952 public void testSandboxForNonResizableActivityPackageOutsideRangeInNeverSandboxDeviceConfig() { 953 ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY; 954 long version = getPackageVersion(activity); 955 try (var neverForApp = setNeverConstrainDisplayApisFlag( 956 "com.android.other::," + activity.getPackageName() + ":" + String.valueOf( 957 version + 1) + ":")) { 958 runSizeCompatModeSandboxTest(activity, /* isSandboxed */ true, 959 /* inSizeCompatModeAfterResize */ true); 960 } 961 } 962 963 /** 964 * Test that a min aspect ratio activity eligible for size compat mode does have the Display 965 * APIs sandboxed when the 'never_constrain_display_apis' Device Config flag doesn't contain the 966 * test package. 967 */ 968 @Test testSandboxForNonResizableActivityPackageNotInNeverSandboxDeviceConfigFlag()969 public void testSandboxForNonResizableActivityPackageNotInNeverSandboxDeviceConfigFlag() { 970 try (var neverForApp = setNeverConstrainDisplayApisFlag( 971 "com.android.other::,com.android.other2::")) { 972 runSizeCompatModeSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, 973 /* isSandboxed */ true, /* inSizeCompatModeAfterResize */ true); 974 } 975 } 976 977 /** 978 * Test that a min aspect ratio activity eligible for size compat mode does have the Display 979 * APIs sandboxed when the 'never_constrain_display_apis' Device Config flag is empty. 980 */ 981 @Test testSandboxForNonResizableActivityNeverSandboxDeviceConfigFlagEmpty()982 public void testSandboxForNonResizableActivityNeverSandboxDeviceConfigFlagEmpty() { 983 try (var empty = setNeverConstrainDisplayApisFlag("")) { 984 runSizeCompatModeSandboxTest(NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY, 985 /* isSandboxed */ true, /* inSizeCompatModeAfterResize */ true); 986 } 987 } 988 989 /** 990 * Test that a min aspect ratio activity eligible for size compat mode does have the Display 991 * APIs sandboxed when the 'never_constrain_display_apis' Device Config flag contains an invalid 992 * entry for the test package. 993 */ 994 @Test testSandboxForNonResizableActivityInvalidEntryInNeverSandboxDeviceConfigFlag()995 public void testSandboxForNonResizableActivityInvalidEntryInNeverSandboxDeviceConfigFlag() { 996 ComponentName activity = NON_RESIZEABLE_LARGE_ASPECT_RATIO_ACTIVITY; 997 try (var neverForApp = setNeverConstrainDisplayApisFlag( 998 "com.android.other::," + activity.getPackageName() + ":::")) { 999 runSizeCompatModeSandboxTest(activity, /* isSandboxed */ true, 1000 /* inSizeCompatModeAfterResize */ true); 1001 } 1002 } 1003 1004 /** ================= 1005 * SANDBOX_VIEW_BOUNDS_APIS test cases 1006 * @see #testSandbox_viewApiForLetterboxedActivity 1007 * @see #testNoSandbox_viewApiForLetterboxedActivity 1008 * @see #testNoSandbox_viewApiForLetterboxedActivityOptOut 1009 * ================= 1010 * Validates that an activity in letterbox mode has sandboxing applied to the 1011 * view bounds when OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS is set. 1012 * Without this flag or with 1013 * {@link android.view.WindowManager#PROPERTY_COMPAT_ALLOW_SANDBOXING_VIEW_BOUNDS_APIS} 1014 * value=false in AndroidManifest.xml 1015 * {@link android.view.View#getLocationOnScreen}, 1016 * {@link android.view.View#getWindowDisplayFrame} 1017 * {@link android.view.View#getBoundsOnScreen} 1018 * and {@link android.view.View#getWindowVisibleDisplayFrame} 1019 * return location or display frame offset by the window location on the screen: 1020 * {@link WindowConfiguration#getBounds} 1021 */ 1022 @Test testSandbox_viewApiForLetterboxedActivity()1023 public void testSandbox_viewApiForLetterboxedActivity() { 1024 // Enable OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS changeId for the test application 1025 try (var aspectRatio = new DisplayAspectRatioCloseable(ORIENTATION_LANDSCAPE, 2.0f); 1026 var compatChange = new CompatChangeCloseable( 1027 OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS, 1028 TEST_VIEW_SANDBOX_ALLOWED_ACTIVITY.getPackageName()); 1029 var receiver = new BroadcastReceiverCloseable(mContext, 1030 ACTION_TEST_VIEW_SANDBOX_ALLOWED_PASSED)) { 1031 1032 try (var session = new ActivitySessionCloseable(TEST_VIEW_SANDBOX_ALLOWED_ACTIVITY)) { 1033 // Wait for the broadcast action 1034 boolean testPassed = receiver 1035 .getBroadcastReceivedVariable(ACTION_TEST_VIEW_SANDBOX_ALLOWED_PASSED) 1036 .block(TEST_VIEW_SANDBOX_ALLOWED_TIMEOUT_MS); 1037 1038 assertThat(testPassed).isTrue(); 1039 } 1040 } 1041 } 1042 1043 @Test testNoSandbox_viewApiForLetterboxedActivity()1044 public void testNoSandbox_viewApiForLetterboxedActivity() { 1045 // Enable OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS changeId for the test application 1046 try (var aspectRatio = new DisplayAspectRatioCloseable(ORIENTATION_LANDSCAPE, 2.0f); 1047 var receiver = new BroadcastReceiverCloseable(mContext, 1048 ACTION_TEST_VIEW_SANDBOX_NOT_ALLOWED_PASSED)) { 1049 1050 try (var session = new ActivitySessionCloseable(TEST_VIEW_SANDBOX_ALLOWED_ACTIVITY)) { 1051 // Wait for the broadcast action 1052 boolean testPassed = receiver 1053 .getBroadcastReceivedVariable(ACTION_TEST_VIEW_SANDBOX_NOT_ALLOWED_PASSED) 1054 .block(TEST_VIEW_SANDBOX_ALLOWED_TIMEOUT_MS); 1055 1056 assertThat(testPassed).isTrue(); 1057 } 1058 } 1059 } 1060 1061 @Test testNoSandbox_viewApiForLetterboxedActivityOptOut()1062 public void testNoSandbox_viewApiForLetterboxedActivityOptOut() { 1063 // Enable OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS changeId for the test application 1064 try (var aspectRatio = new DisplayAspectRatioCloseable(ORIENTATION_LANDSCAPE, 2.0f); 1065 var compatChange = new CompatChangeCloseable( 1066 OVERRIDE_SANDBOX_VIEW_BOUNDS_APIS, 1067 TEST_VIEW_SANDBOX_OPT_OUT_ACTIVITY.getPackageName()); 1068 var receiver = new BroadcastReceiverCloseable(mContext, 1069 ACTION_TEST_VIEW_SANDBOX_OPT_OUT_PASSED)) { 1070 1071 try (var session = new ActivitySessionCloseable(TEST_VIEW_SANDBOX_OPT_OUT_ACTIVITY)) { 1072 // Wait for the broadcast action 1073 boolean testPassed = receiver 1074 .getBroadcastReceivedVariable(ACTION_TEST_VIEW_SANDBOX_OPT_OUT_PASSED) 1075 .block(TEST_VIEW_SANDBOX_OPT_OUT_TIMEOUT_MS); 1076 1077 assertThat(testPassed).isTrue(); 1078 } 1079 } 1080 } 1081 1082 // ================= 1083 // ALWAYS_SANDBOX test cases 1084 // ================= 1085 // Validates that an activity simply in letterbox mode has sandboxing applied to the max 1086 // bounds when ALWAYS_SANDBOX is set. Without the flag, we would not expect a letterbox activity 1087 // to be sandboxed, unless it is also eligible for size compat mode. 1088 1089 /** 1090 * Test that a portrait activity not eligible for size compat mode does have the 1091 * Display APIs sandboxed when the {@link ActivityInfo#ALWAYS_SANDBOX_DISPLAY_APIS} compat 1092 * change is enabled. 1093 */ 1094 @Test 1095 @EnableCompatChanges({ActivityInfo.ALWAYS_SANDBOX_DISPLAY_APIS}) testSandboxForResizableActivityAlwaysSandboxDisplayApisEnabled()1096 public void testSandboxForResizableActivityAlwaysSandboxDisplayApisEnabled() { 1097 runLetterboxSandboxTest(RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed */ true); 1098 } 1099 1100 /** 1101 * Test that a portrait activity not eligible for size compat mode does not have the 1102 * Display APIs sandboxed when the 'always_constrain_display_apis' Device Config flag is empty. 1103 */ 1104 @Test testSandboxResizableActivityAlwaysSandboxDeviceConfigFlagEmpty()1105 public void testSandboxResizableActivityAlwaysSandboxDeviceConfigFlagEmpty() { 1106 runLetterboxSandboxTest(RESIZEABLE_PORTRAIT_ACTIVITY, /* isSandboxed */ false); 1107 } 1108 1109 /** 1110 * Test that a portrait activity not eligible for size compat mode does have the Display 1111 * APIs sandboxed when the 'always_constrain_display_apis' Device Config flag contains the test 1112 * package. 1113 */ 1114 @Test testSandboxResizableActivityPackageInAlwaysSandboxDeviceConfigFlag()1115 public void testSandboxResizableActivityPackageInAlwaysSandboxDeviceConfigFlag() { 1116 ComponentName activity = RESIZEABLE_PORTRAIT_ACTIVITY; 1117 try (var alwaysForApp = setAlwaysConstrainDisplayApisFlag( 1118 "com.android.other::," + activity.getPackageName() + "::")) { 1119 runLetterboxSandboxTest(activity, /* isSandboxed */ true); 1120 } 1121 } 1122 1123 /** 1124 * Test that only applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} has no effect on its 1125 * own. The aspect ratio of the activity should be the same as that of the task, which should be 1126 * in line with that of the display. 1127 */ 1128 @Test 1129 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) testOverrideMinAspectRatioMissingSpecificOverride()1130 public void testOverrideMinAspectRatioMissingSpecificOverride() { 1131 runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* expected */ 0); 1132 } 1133 1134 /** 1135 * Test that only applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} has no effect on 1136 * its own without the presence of {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO}. 1137 */ 1138 @Test 1139 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) testOverrideMinAspectRatioMissingGeneralOverride()1140 public void testOverrideMinAspectRatioMissingGeneralOverride() { 1141 runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, /* expected */ 0); 1142 } 1143 1144 /** 1145 * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} has no effect on 1146 * activities whose orientation is fixed to landscape. 1147 */ 1148 @Test 1149 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1150 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) testOverrideMinAspectRatioForLandscapeActivity()1151 public void testOverrideMinAspectRatioForLandscapeActivity() { 1152 runMinAspectRatioTest(NON_RESIZEABLE_LANDSCAPE_ACTIVITY, /* expected */ 0); 1153 } 1154 1155 /** 1156 * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} has no effect on 1157 * activities whose orientation isn't fixed. 1158 */ 1159 @Test 1160 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1161 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) 1162 @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY}) testOverrideMinAspectRatioForNonFixedOrientationActivityPortraitOnlyDisabled()1163 public void testOverrideMinAspectRatioForNonFixedOrientationActivityPortraitOnlyDisabled() { 1164 runMinAspectRatioTest(NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY, /* expected */ 1165 OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); 1166 } 1167 1168 /** 1169 * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} has no effect on 1170 * activities whose orientation is fixed to landscape. 1171 */ 1172 @Test 1173 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1174 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) 1175 @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY}) testOverrideMinAspectRatioForLandscapeActivityPortraitOnlyDisabled()1176 public void testOverrideMinAspectRatioForLandscapeActivityPortraitOnlyDisabled() { 1177 runMinAspectRatioTest(NON_RESIZEABLE_LANDSCAPE_ACTIVITY, /* expected */ 1178 OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); 1179 } 1180 1181 /** 1182 * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} has no effect on 1183 * activities whose orientation isn't fixed. 1184 */ 1185 @Test 1186 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1187 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) testOverrideMinAspectRatioForNonFixedOrientationActivity()1188 public void testOverrideMinAspectRatioForNonFixedOrientationActivity() { 1189 runMinAspectRatioTest(NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY, /* expected */ 0); 1190 } 1191 1192 /** 1193 * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE} sets the min aspect 1194 * ratio to {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE}. 1195 */ 1196 @Test 1197 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1198 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) testOverrideMinAspectRatioLargeAspectRatio()1199 public void testOverrideMinAspectRatioLargeAspectRatio() { 1200 runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, 1201 /* expected */ OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); 1202 } 1203 1204 /** 1205 * Test that applying {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_MEDIUM} sets the min aspect 1206 * ratio to {@link ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE}. 1207 */ 1208 @Test 1209 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1210 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) testOverrideMinAspectRatioMediumAspectRatio()1211 public void testOverrideMinAspectRatioMediumAspectRatio() { 1212 runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, 1213 /* expected */ OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE); 1214 } 1215 1216 /** 1217 * Test that applying multiple min aspect ratio overrides result in the largest one taking 1218 * effect. 1219 */ 1220 @Test 1221 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1222 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE, 1223 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) testOverrideMinAspectRatioBothAspectRatios()1224 public void testOverrideMinAspectRatioBothAspectRatios() { 1225 runMinAspectRatioTest(NON_RESIZEABLE_PORTRAIT_ACTIVITY, 1226 /* expected */ OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); 1227 } 1228 1229 /** 1230 * Test that the min aspect ratio of the activity as defined in the manifest is ignored if 1231 * there is an override for a larger min aspect ratio present (16:9 > 1.6). 1232 */ 1233 @Test 1234 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1235 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE}) testOverrideMinAspectRatioActivityMinAspectRatioSmallerThanOverride()1236 public void testOverrideMinAspectRatioActivityMinAspectRatioSmallerThanOverride() { 1237 runMinAspectRatioTest(NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY, 1238 /* expected */ OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE); 1239 } 1240 1241 /** 1242 * Test that the min aspect ratio of the activity as defined in the manifest is upheld if 1243 * there is an override for a smaller min aspect ratio present (3:2 < 1.6). 1244 */ 1245 @Test 1246 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO, 1247 ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM}) testOverrideMinAspectRatioActivityMinAspectRatioLargerThanOverride()1248 public void testOverrideMinAspectRatioActivityMinAspectRatioLargerThanOverride() { 1249 runMinAspectRatioTest(NON_RESIZEABLE_ASPECT_RATIO_ACTIVITY, 1250 /* expected */ ACTIVITY_MIN_ASPECT_RATIO); 1251 } 1252 1253 /** 1254 * Test that an activities min aspect ratio is overridden when {@link 1255 * ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} is enabled and {@link 1256 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE} is true. 1257 */ 1258 @Test 1259 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO", 1260 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"}) 1261 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideMinAspectRatio_propertyTrue_overrideEnabled_overrideApplied()1262 public void testOverrideMinAspectRatio_propertyTrue_overrideEnabled_overrideApplied() { 1263 try (var compatChange = new CompatChangeCloseable(OVERRIDE_MIN_ASPECT_RATIO, 1264 ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY.getPackageName()); 1265 var session = new ActivitySessionCloseable( 1266 ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY)) { 1267 assertTrue(session.getActivityState().getShouldOverrideMinAspectRatio()); 1268 } 1269 } 1270 1271 /** 1272 * Test that an activities min aspect ratio is not overridden when {@link 1273 * ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} is enabled but {@link 1274 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE} is false. 1275 */ 1276 @Test 1277 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO", 1278 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"}) 1279 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideMinAspectRatio_propertyFalse_overrideEnabled_overrideNotApplied()1280 public void testOverrideMinAspectRatio_propertyFalse_overrideEnabled_overrideNotApplied() { 1281 try (var compatChange = new CompatChangeCloseable(OVERRIDE_MIN_ASPECT_RATIO, 1282 ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY.getPackageName()); 1283 var session = new ActivitySessionCloseable( 1284 ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_OUT_ACTIVITY)) { 1285 assertFalse(session.getActivityState().getShouldOverrideMinAspectRatio()); 1286 } 1287 } 1288 1289 /** 1290 * Test that an activities min aspect ratio is overridden when {@link 1291 * ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} is enabled and {@link 1292 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE} is unset. 1293 */ 1294 @Test 1295 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO", 1296 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"}) 1297 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 1298 @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) testOverrideMinAspectRatio_propertyNotSet_overrideEnabled_overrideApplied()1299 public void testOverrideMinAspectRatio_propertyNotSet_overrideEnabled_overrideApplied() { 1300 try (var session = new ActivitySessionCloseable( 1301 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 1302 assertTrue(session.getActivityState().getShouldOverrideMinAspectRatio()); 1303 } 1304 } 1305 1306 /** 1307 * Test that an activities min aspect ratio is not overridden when {@link 1308 * ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} is disabled and {@link 1309 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE} is unset. 1310 */ 1311 @Test 1312 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO", 1313 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"}) 1314 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 1315 @DisableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO}) testOverrideMinAspectRatio_propertyNotSet_overrideDisabled_overrideNotApplied()1316 public void testOverrideMinAspectRatio_propertyNotSet_overrideDisabled_overrideNotApplied() { 1317 try (var session = new ActivitySessionCloseable( 1318 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 1319 assertFalse(session.getActivityState().getShouldOverrideMinAspectRatio()); 1320 } 1321 } 1322 1323 /** 1324 * Test that an activities min aspect ratio is not overridden when {@link 1325 * ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} is disabled but {@link 1326 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE} is true. 1327 */ 1328 @Test 1329 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO", 1330 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"}) 1331 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideMinAspectRatio_propertyTrue_overrideUnset_overrideNotApplied()1332 public void testOverrideMinAspectRatio_propertyTrue_overrideUnset_overrideNotApplied() { 1333 try (var session = new ActivitySessionCloseable( 1334 ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY)) { 1335 assertFalse(session.getActivityState().getShouldOverrideMinAspectRatio()); 1336 } 1337 } 1338 1339 /** 1340 * Test that an activities min aspect ratio is not overridden when {@link 1341 * ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO} is disabled and {@link 1342 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE} is false. 1343 */ 1344 @Test 1345 @ApiTest(apis = {"android.content.pm.ActivityInfo#OVERRIDE_MIN_ASPECT_RATIO", 1346 "android.view.WindowManager#PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE"}) 1347 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testOverrideMinAspectRatio_propertyFalse_overrideUnset_overrideNotApplied()1348 public void testOverrideMinAspectRatio_propertyFalse_overrideUnset_overrideNotApplied() { 1349 try (var session = new ActivitySessionCloseable( 1350 ALLOW_MIN_ASPECT_RATIO_OVERRIDE_OPT_OUT_ACTIVITY)) { 1351 assertFalse(session.getActivityState().getShouldOverrideMinAspectRatio()); 1352 } 1353 } 1354 1355 /** 1356 * Test that the user aspect ratio settings are enabled when {@link 1357 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is set to true 1358 * and {@link com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled} 1359 * is true. 1360 */ 1361 @Test 1362 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1363 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioSettings_propertyTrue_configEnabled_overrideAllowed()1364 public void testAllowUserAspectRatioSettings_propertyTrue_configEnabled_overrideAllowed() { 1365 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1366 isUserAppAspectRatioSettingsIsEnabled()); 1367 1368 try (var session = new ActivitySessionCloseable( 1369 ALLOW_USER_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY)) { 1370 assertTrue(session.getActivityState().getShouldEnableUserAspectRatioSettings()); 1371 } 1372 } 1373 1374 /** 1375 * Test that the user aspect ratio settings are disabled when {@link 1376 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is set to true 1377 * but {@link com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled} 1378 * is false. 1379 */ 1380 @Test 1381 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1382 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioSettings_propertyTrue_configDisabled_overrideNotAllowed()1383 public void testAllowUserAspectRatioSettings_propertyTrue_configDisabled_overrideNotAllowed() { 1384 assumeFalse("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled is enabled", 1385 isUserAppAspectRatioSettingsIsEnabled()); 1386 1387 try (var session = new ActivitySessionCloseable( 1388 ALLOW_USER_ASPECT_RATIO_OVERRIDE_OPT_IN_ACTIVITY)) { 1389 assertFalse(session.getActivityState().getShouldEnableUserAspectRatioSettings()); 1390 } 1391 } 1392 1393 /** 1394 * Test that the user aspect ratio settings are disabled when {@link 1395 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is set to false 1396 * but {@link com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled} 1397 * is true. 1398 */ 1399 @Test 1400 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1401 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioSettings_propertyFalse_configEnabled_overrideNotAllowed()1402 public void testAllowUserAspectRatioSettings_propertyFalse_configEnabled_overrideNotAllowed() { 1403 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1404 isUserAppAspectRatioSettingsIsEnabled()); 1405 1406 try (var session = new ActivitySessionCloseable( 1407 ALLOW_USER_ASPECT_RATIO_OVERRIDE_OPT_OUT_ACTIVITY)) { 1408 assertFalse(session.getActivityState().getShouldEnableUserAspectRatioSettings()); 1409 } 1410 } 1411 1412 /** 1413 * Test that the user aspect ratio settings are disabled when {@link 1414 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is set to false 1415 * and {@link com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled} 1416 * is false. 1417 */ 1418 @Test 1419 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1420 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioSettings_propertyFalse_configDisabled_overrideNotAllowed()1421 public void testAllowUserAspectRatioSettings_propertyFalse_configDisabled_overrideNotAllowed() { 1422 assumeFalse("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled is enabled", 1423 isUserAppAspectRatioSettingsIsEnabled()); 1424 1425 try (var session = new ActivitySessionCloseable( 1426 ALLOW_USER_ASPECT_RATIO_OVERRIDE_OPT_OUT_ACTIVITY)) { 1427 assertFalse(session.getActivityState().getShouldEnableUserAspectRatioSettings()); 1428 } 1429 } 1430 1431 /** 1432 * Test that the user aspect ratio settings are enabled when {@link 1433 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is unset and 1434 * {@link com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled} 1435 * is true. 1436 */ 1437 @Test 1438 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1439 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioSettings_propertyUnset_configEnabled_overrideAllowed()1440 public void testAllowUserAspectRatioSettings_propertyUnset_configEnabled_overrideAllowed() { 1441 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1442 isUserAppAspectRatioSettingsIsEnabled()); 1443 1444 try (var session = new ActivitySessionCloseable( 1445 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 1446 assertTrue(session.getActivityState().getShouldEnableUserAspectRatioSettings()); 1447 } 1448 } 1449 1450 /** 1451 * Test that the user aspect ratio settings are disabled when {@link 1452 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE} is unset but 1453 * {@link com.android.internal.R.bool.config_appCompatUserAppAspectRatioSettingsIsEnabled} 1454 * is false. 1455 */ 1456 @Test 1457 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1458 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioSettings_propertyUnset_configDisabled_overrideNotAllowed()1459 public void testAllowUserAspectRatioSettings_propertyUnset_configDisabled_overrideNotAllowed() { 1460 assumeFalse("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled is enabled", 1461 isUserAppAspectRatioSettingsIsEnabled()); 1462 1463 try (var session = new ActivitySessionCloseable( 1464 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 1465 assertFalse(session.getActivityState().getShouldEnableUserAspectRatioSettings()); 1466 } 1467 } 1468 1469 /** 1470 * Test that the user aspect ratio fullscreen override is applicable through the user aspect 1471 * ratio settings when {@link 1472 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} is 1473 * set to true and {@link 1474 * com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled} is true. 1475 */ 1476 @Test 1477 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1478 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioFullscreen_propertyTrue_configEnabled_overrideAllowed()1479 public void testAllowUserAspectRatioFullscreen_propertyTrue_configEnabled_overrideAllowed() { 1480 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1481 isUserAppAspectRatioSettingsIsEnabled()); 1482 assumeTrue( 1483 "Skipping test: config_appCompatUserAppAspectRatioFullscreenIsEnabled not enabled", 1484 isUserAppAspectRatioFullscreenIsEnabled()); 1485 1486 try (var session = new ActivitySessionCloseable( 1487 ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE_OPT_IN_ACTIVITY)) { 1488 assertTrue(session.getActivityState().getIsUserFullscreenOverrideEnabled()); 1489 } 1490 } 1491 1492 /** 1493 * Test that the user aspect ratio fullscreen override is not applicable through the user aspect 1494 * ratio settings when {@link 1495 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} is 1496 * set to true but {@link 1497 * com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled} is false. 1498 */ 1499 @Test 1500 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1501 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 1502 public void testAllowUserAspectRatioFullscreen_propertyTrue_configDisabled_overrideNotAllowed()1503 testAllowUserAspectRatioFullscreen_propertyTrue_configDisabled_overrideNotAllowed() { 1504 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1505 isUserAppAspectRatioSettingsIsEnabled()); 1506 assumeFalse( 1507 "Skipping test: config_appCompatUserAppAspectRatioFullscreenIsEnabled is enabled", 1508 isUserAppAspectRatioFullscreenIsEnabled()); 1509 1510 try (var session = new ActivitySessionCloseable( 1511 ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE_OPT_IN_ACTIVITY)) { 1512 assertFalse(session.getActivityState().getIsUserFullscreenOverrideEnabled()); 1513 } 1514 } 1515 1516 /** 1517 * Test that the user aspect ratio fullscreen override is not applicable through the user aspect 1518 * ratio settings when {@link 1519 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} is 1520 * set to false but {@link 1521 * com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled} is true. 1522 */ 1523 @Test 1524 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1525 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 1526 public void testAllowUserAspectRatioFullscreen_propertyFalse_configEnabled_overrideNotAllowed()1527 testAllowUserAspectRatioFullscreen_propertyFalse_configEnabled_overrideNotAllowed() { 1528 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1529 isUserAppAspectRatioSettingsIsEnabled()); 1530 assumeTrue( 1531 "Skipping test: config_appCompatUserAppAspectRatioFullscreenIsEnabled not enabled", 1532 isUserAppAspectRatioFullscreenIsEnabled()); 1533 1534 try (var session = new ActivitySessionCloseable( 1535 ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE_OPT_OUT_ACTIVITY)) { 1536 assertFalse(session.getActivityState().getIsUserFullscreenOverrideEnabled()); 1537 } 1538 } 1539 1540 /** 1541 * Test that the user aspect ratio fullscreen override is not applicable through the user aspect 1542 * ratio settings when {@link 1543 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} is 1544 * set to false and {@link 1545 * com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled} is false. 1546 */ 1547 @Test 1548 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1549 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 1550 public void testAllowUserAspectRatioFullscreen_propertyFalse_configDisabled_overrideNotAllowed()1551 testAllowUserAspectRatioFullscreen_propertyFalse_configDisabled_overrideNotAllowed() { 1552 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1553 isUserAppAspectRatioSettingsIsEnabled()); 1554 assumeFalse( 1555 "Skipping test: config_appCompatUserAppAspectRatioFullscreenIsEnabled is enabled", 1556 isUserAppAspectRatioFullscreenIsEnabled()); 1557 1558 try (var session = new ActivitySessionCloseable( 1559 ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE_OPT_OUT_ACTIVITY)) { 1560 assertFalse(session.getActivityState().getIsUserFullscreenOverrideEnabled()); 1561 } 1562 } 1563 1564 /** 1565 * Test that the user aspect ratio fullscreen override is applicable through the user aspect 1566 * ratio settings when {@link 1567 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} is 1568 * unset but {@link 1569 * com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled} is true. 1570 */ 1571 @Test 1572 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1573 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) testAllowUserAspectRatioFullscreen_propertyUnset_configEnabled_overrideAllowed()1574 public void testAllowUserAspectRatioFullscreen_propertyUnset_configEnabled_overrideAllowed() { 1575 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1576 isUserAppAspectRatioSettingsIsEnabled()); 1577 assumeTrue( 1578 "Skipping test: config_appCompatUserAppAspectRatioFullscreenIsEnabled not enabled", 1579 isUserAppAspectRatioFullscreenIsEnabled()); 1580 1581 try (var session = new ActivitySessionCloseable( 1582 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 1583 assertTrue(session.getActivityState().getIsUserFullscreenOverrideEnabled()); 1584 } 1585 } 1586 1587 /** 1588 * Test that the user aspect ratio fullscreen override is not applicable through the user aspect 1589 * ratio settings when {@link 1590 * android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE} is 1591 * set to unset but {@link 1592 * com.android.internal.R.bool.config_appCompatUserAppAspectRatioFullscreenIsEnabled} is false. 1593 */ 1594 @Test 1595 @ApiTest(apis = {"android.view.WindowManager#PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE"}) 1596 @RequiresFlagsEnabled(Flags.FLAG_APP_COMPAT_PROPERTIES_API) 1597 public void testAllowUserAspectRatioFullscreen_propertyUnset_configDisabled_overrideNotAllowed()1598 testAllowUserAspectRatioFullscreen_propertyUnset_configDisabled_overrideNotAllowed() { 1599 assumeTrue("Skipping test: config_appCompatUserAppAspectRatioSettingsIsEnabled not enabled", 1600 isUserAppAspectRatioSettingsIsEnabled()); 1601 assumeFalse( 1602 "Skipping test: config_appCompatUserAppAspectRatioFullscreenIsEnabled is enabled", 1603 isUserAppAspectRatioFullscreenIsEnabled()); 1604 1605 try (var session = new ActivitySessionCloseable( 1606 NON_RESIZEABLE_NON_FIXED_ORIENTATION_ACTIVITY)) { 1607 assertFalse(session.getActivityState().getIsUserFullscreenOverrideEnabled()); 1608 } 1609 } 1610 isUserAppAspectRatioFullscreenIsEnabled()1611 private boolean isUserAppAspectRatioFullscreenIsEnabled() { 1612 return getBooleanConfig("config_appCompatUserAppAspectRatioFullscreenIsEnabled"); 1613 } 1614 isUserAppAspectRatioSettingsIsEnabled()1615 private boolean isUserAppAspectRatioSettingsIsEnabled() { 1616 return getBooleanConfig("config_appCompatUserAppAspectRatioSettingsIsEnabled"); 1617 } 1618 isCameraCompatForceRotationTreatmentConfigEnabled()1619 private boolean isCameraCompatForceRotationTreatmentConfigEnabled() { 1620 return getBooleanConfig("config_isWindowManagerCameraCompatTreatmentEnabled"); 1621 } 1622 isPolicyForIgnoringRequestedOrientationEnabled()1623 private boolean isPolicyForIgnoringRequestedOrientationEnabled() { 1624 return getBooleanConfig("config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled"); 1625 } 1626 getBooleanConfig(String configName)1627 private boolean getBooleanConfig(String configName) { 1628 return mContext.getResources().getBoolean( 1629 Resources.getSystem().getIdentifier(configName, "bool", "android")); 1630 } 1631 1632 /** 1633 * Launches the provided activity into size compat mode twice. The first time, the display 1634 * is resized to be half the size. The second time, the display is resized to be twice the 1635 * original size. 1636 * 1637 * @param activity the activity under test. 1638 * @param inSizeCompatModeAfterResize if the activity should be in size compat mode after 1639 * resizing the display 1640 */ runSizeCompatTest(ComponentName activity, boolean inSizeCompatModeAfterResize)1641 private void runSizeCompatTest(ComponentName activity, boolean inSizeCompatModeAfterResize) { 1642 try (var session = new ActivitySessionCloseable(activity)) { 1643 runSizeCompatTestForActivity(activity, /* resizeRatio */ 0.5, 1644 inSizeCompatModeAfterResize); 1645 } 1646 1647 try (var session = new ActivitySessionCloseable(activity)) { 1648 runSizeCompatTestForActivity(activity, /* resizeRatio */ 2, 1649 inSizeCompatModeAfterResize); 1650 } 1651 } 1652 1653 /** 1654 * Launches the provided activity on the default display, initially not in size compat mode. 1655 * After resizing the display, verifies if activity is in size compat mode or not 1656 * 1657 * @param activity the activity under test 1658 * @param resizeRatio the ratio to resize the display 1659 * @param inSizeCompatModeAfterResize if the activity should be in size compat mode after 1660 * resizing the display 1661 */ runSizeCompatTestForActivity(ComponentName activity, final double resizeRatio, final boolean inSizeCompatModeAfterResize)1662 private void runSizeCompatTestForActivity(ComponentName activity, final double resizeRatio, 1663 final boolean inSizeCompatModeAfterResize) { 1664 1665 waitAndAssertSizeCompatMode(activity, /* expectedInSizeCompatMode */ false); 1666 1667 try (var resized = new DisplaySizeScaleCloseable(resizeRatio, activity)) { 1668 assertThat(resized.getInitialDisplayAspectRatio()) 1669 .isLessThan(ACTIVITY_LARGE_MIN_ASPECT_RATIO); 1670 waitAndAssertSizeCompatMode(activity, inSizeCompatModeAfterResize); 1671 } 1672 } 1673 waitAndAssertSizeCompatMode(final ComponentName activity, final boolean expectedInSizeCompatMode)1674 private void waitAndAssertSizeCompatMode(final ComponentName activity, 1675 final boolean expectedInSizeCompatMode) { 1676 waitAssertEquals("The window must be inSizeCompatMode==" + expectedInSizeCompatMode, 1677 expectedInSizeCompatMode, 1678 () -> getActivityWaitState(activity).inSizeCompatMode()); 1679 } 1680 1681 /** 1682 * Similar to {@link #runSizeCompatTest(ComponentName, boolean)}, but the activity is 1683 * expected to be in size compat mode after resizing the display. 1684 * 1685 * @param activity the activity under test 1686 * @param isSandboxed when {@code true}, 1687 * {@link android.app.WindowConfiguration#getMaxBounds()} 1688 * are sandboxed to the activity bounds. Otherwise, they 1689 * inherit the 1690 * DisplayArea bounds 1691 * @param inSizeCompatModeAfterResize if the activity should be in size compat mode after 1692 * resizing the display 1693 */ runSizeCompatModeSandboxTest(ComponentName activity, boolean isSandboxed, boolean inSizeCompatModeAfterResize)1694 private void runSizeCompatModeSandboxTest(ComponentName activity, boolean isSandboxed, 1695 boolean inSizeCompatModeAfterResize) { 1696 try (var session = new ActivitySessionCloseable(activity, WINDOWING_MODE_FULLSCREEN)) { 1697 runSizeCompatTestForActivity(activity, /* resizeRatio */ 0.5, 1698 inSizeCompatModeAfterResize); 1699 assertSandboxedByProvidesMaxBounds(activity, isSandboxed); 1700 assertSandboxedByBounds(activity, isSandboxed); 1701 } 1702 1703 try (var session = new ActivitySessionCloseable(activity, WINDOWING_MODE_FULLSCREEN)) { 1704 runSizeCompatTestForActivity(activity, /* resizeRatio */ 2, 1705 inSizeCompatModeAfterResize); 1706 assertSandboxedByProvidesMaxBounds(activity, isSandboxed); 1707 assertSandboxedByBounds(activity, isSandboxed); 1708 } 1709 } 1710 1711 /** 1712 * Similar to {@link #runSizeCompatModeSandboxTest(ComponentName, boolean, boolean)}, but the 1713 * activity is put into letterbox mode after resizing the display. 1714 * 1715 * @param activityName the activity under test 1716 * @param isSandboxed when {@code true}, {@link android.app.WindowConfiguration#getMaxBounds()} 1717 * are sandboxed to the activity bounds. Otherwise, they inherit the 1718 * DisplayArea bounds 1719 */ runLetterboxSandboxTest(ComponentName activityName, boolean isSandboxed)1720 private void runLetterboxSandboxTest(ComponentName activityName, boolean isSandboxed) { 1721 try (var aspectRatio = new DisplayAspectRatioCloseable(ORIENTATION_LANDSCAPE, 2.0f)) { 1722 assertThat(aspectRatio.getInitialDisplayAspectRatio()) 1723 .isLessThan(ACTIVITY_LARGE_MIN_ASPECT_RATIO); 1724 1725 try (var session = new ActivitySessionCloseable(activityName)) { 1726 assertSandboxedByProvidesMaxBounds(activityName, isSandboxed); 1727 } 1728 } 1729 } 1730 assertSandboxedByBounds(ComponentName activityName, boolean isSandboxed)1731 private void assertSandboxedByBounds(ComponentName activityName, boolean isSandboxed) { 1732 final WindowManagerState.Activity activity = getActivityWaitState(activityName); 1733 assertNotNull(activity); 1734 final Rect activityBounds = activity.getBounds(); 1735 final Rect maxBounds = activity.getMaxBounds(); 1736 WindowManagerState.DisplayArea tda = mWmState.getTaskDisplayArea(activityName); 1737 assertNotNull(tda); 1738 if (isSandboxed) { 1739 assertEquals( 1740 "The window has max bounds sandboxed to the window bounds", 1741 activityBounds, maxBounds); 1742 } else { 1743 assertEquals( 1744 "The window is not sandboxed, with max bounds reflecting the DisplayArea", 1745 tda.getBounds(), maxBounds); 1746 } 1747 } 1748 assertSandboxedByProvidesMaxBounds(ComponentName activityName, boolean isSandboxed)1749 private void assertSandboxedByProvidesMaxBounds(ComponentName activityName, 1750 boolean isSandboxed) { 1751 final WindowManagerState.Activity activity = getActivityWaitState(activityName); 1752 assertNotNull(activity); 1753 if (isSandboxed) { 1754 assertTrue( 1755 "The window should have max bounds sandboxed to the window bounds", 1756 activity.providesMaxBounds()); 1757 } else { 1758 assertFalse( 1759 "The window should not be sandboxed; max bounds should reflect the DisplayArea", 1760 activity.providesMaxBounds()); 1761 } 1762 } 1763 setNeverConstrainDisplayApisFlag(@ullable String value)1764 private CloseableDeviceConfig setNeverConstrainDisplayApisFlag(@Nullable String value) { 1765 return setConstrainDisplayApisFlag("never_constrain_display_apis", value); 1766 } 1767 setNeverConstrainDisplayApisAllPackagesFlag( @ullable String value)1768 private CloseableDeviceConfig setNeverConstrainDisplayApisAllPackagesFlag( 1769 @Nullable String value) { 1770 return setConstrainDisplayApisFlag("never_constrain_display_apis_all_packages", value); 1771 } 1772 setAlwaysConstrainDisplayApisFlag( @ullable String value)1773 private CloseableDeviceConfig setAlwaysConstrainDisplayApisFlag( 1774 @Nullable String value) { 1775 return setConstrainDisplayApisFlag("always_constrain_display_apis", value); 1776 } 1777 setConstrainDisplayApisFlag(@onNull String flagName, @Nullable String value)1778 private CloseableDeviceConfig setConstrainDisplayApisFlag(@NonNull String flagName, 1779 @Nullable String value) { 1780 return new CloseableDeviceConfig(NAMESPACE_CONSTRAIN_DISPLAY_APIS, flagName, value); 1781 } 1782 1783 /** 1784 * Launches the provided activity and verifies that its min aspect ratio is equal to {@code 1785 * expected}. 1786 * 1787 * @param activity the activity under test. 1788 * @param expected the expected min aspect ratio in both portrait and landscape displays. 1789 */ runMinAspectRatioTest(ComponentName activity, float expected)1790 private void runMinAspectRatioTest(ComponentName activity, float expected) { 1791 try (var session = new ActivitySessionCloseable(activity)) { 1792 assertNotNull(session.getActivityState()); 1793 assertEquals(expected, 1794 session.getActivityState().getMinAspectRatio(), 1795 FLOAT_EQUALITY_DELTA); 1796 } 1797 } 1798 getPackageVersion(ComponentName activity)1799 private long getPackageVersion(ComponentName activity) { 1800 try { 1801 return mContext.getPackageManager().getPackageInfo(activity.getPackageName(), 1802 /* flags */ 0).getLongVersionCode(); 1803 } catch (PackageManager.NameNotFoundException e) { 1804 throw new RuntimeException(e); 1805 } 1806 } 1807 component(Class<? extends Activity> activity)1808 private static ComponentName component(Class<? extends Activity> activity) { 1809 return new ComponentName(getInstrumentation().getContext(), activity); 1810 } 1811 1812 public static class ResizeablePortraitActivity extends AbstractLifecycleLogActivity { 1813 } 1814 1815 public static class ResponsiveActivity extends AbstractLifecycleLogActivity { 1816 } 1817 1818 public static class NonResizeablePortraitActivity extends AbstractLifecycleLogActivity { 1819 } 1820 1821 public static class NonResizeableLandscapeActivity extends AbstractLifecycleLogActivity { 1822 } 1823 1824 public static class NonResizeableNonFixedOrientationActivity extends 1825 AbstractLifecycleLogActivity { 1826 } 1827 1828 public static class NonResizeableAspectRatioActivity extends AbstractLifecycleLogActivity { 1829 } 1830 1831 public static class NonResizeableLargeAspectRatioActivity extends AbstractLifecycleLogActivity { 1832 } 1833 1834 public static class SupportsSizeChangesPortraitActivity extends AbstractLifecycleLogActivity { 1835 } 1836 1837 public static class ResizeableLeftActivity extends AbstractLifecycleLogActivity { 1838 } 1839 1840 public static class ResizeableRightActivity extends AbstractLifecycleLogActivity { 1841 } 1842 1843 public static class NoPropertyChangeOrientationWhileRelaunchingActivity extends 1844 AbstractLifecycleLogActivity { 1845 1846 private static boolean sHasChangeOrientationInOnResume; 1847 1848 @Override onCreate(Bundle instance)1849 protected void onCreate(Bundle instance) { 1850 super.onCreate(instance); 1851 // When OVERRIDE_ENABLE_COMPAT_IGNORE_REQUESTED_ORIENTATION is enabled this request 1852 // should be ignored if sHasChangeOrientationInOnResume is true. 1853 setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE); 1854 } 1855 1856 @Override onResume()1857 protected void onResume() { 1858 super.onResume(); 1859 if (!sHasChangeOrientationInOnResume) { 1860 setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT); 1861 sHasChangeOrientationInOnResume = true; 1862 } 1863 } 1864 } 1865 1866 /** 1867 * Registers broadcast receiver which receives result actions from Activities under test. 1868 */ 1869 private static class BroadcastReceiverCloseable implements AutoCloseable { 1870 private final Context mContext; 1871 private final Map<String, ConditionVariable> mBroadcastsReceived; 1872 private final BroadcastReceiver mAppCommunicator = new BroadcastReceiver() { 1873 @Override 1874 public void onReceive(Context context, Intent intent) { 1875 getBroadcastReceivedVariable(intent.getAction()).open(); 1876 } 1877 }; 1878 BroadcastReceiverCloseable(final Context context, final String action)1879 BroadcastReceiverCloseable(final Context context, final String action) { 1880 this.mContext = context; 1881 // Keep the received broadcast items in the map. 1882 mBroadcastsReceived = Collections.synchronizedMap(new HashMap<>()); 1883 // Register for broadcast actions. 1884 IntentFilter filter = new IntentFilter(); 1885 filter.addAction(action); 1886 mContext.registerReceiver(mAppCommunicator, filter, Context.RECEIVER_EXPORTED); 1887 } 1888 getBroadcastReceivedVariable(String action)1889 ConditionVariable getBroadcastReceivedVariable(String action) { 1890 return mBroadcastsReceived.computeIfAbsent(action, key -> new ConditionVariable()); 1891 } 1892 1893 @Override close()1894 public void close() { 1895 mContext.unregisterReceiver(mAppCommunicator); 1896 } 1897 } 1898 1899 /** 1900 * Resets device config to the original value after the try-with-resources block finishes 1901 * try (var dc = new CloseableDeviceConfig()) {...} 1902 */ 1903 private class CloseableDeviceConfig implements AutoCloseable { 1904 private String mOriginalValue; 1905 private final String mNamespace; 1906 private final String mFlagName; 1907 CloseableDeviceConfig(@onNull String namespace, @NonNull String flagName, @Nullable String value)1908 CloseableDeviceConfig(@NonNull String namespace, @NonNull String flagName, 1909 @Nullable String value) { 1910 mNamespace = namespace; 1911 mFlagName = flagName; 1912 runWithShellPermission(() -> { 1913 mOriginalValue = DeviceConfig.getProperty(namespace, flagName); 1914 DeviceConfig.setProperty(namespace, flagName, value, /* makeDefault */ 1915 false); 1916 }); 1917 } 1918 1919 @Override close()1920 public void close() { 1921 runWithShellPermission(() -> DeviceConfig.setProperty(mNamespace, mFlagName, 1922 mOriginalValue, /* makeDefault */ false)); 1923 } 1924 } 1925 } 1926