1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 20 import static android.app.servertransaction.ActivityLifecycleItem.ON_PAUSE; 21 import static android.app.servertransaction.ActivityLifecycleItem.ON_STOP; 22 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; 23 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; 24 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 25 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; 26 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 27 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 28 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 29 import static android.view.Surface.ROTATION_0; 30 import static android.view.Surface.ROTATION_90; 31 32 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 33 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; 35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 36 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 37 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 38 39 import static org.junit.Assert.assertEquals; 40 import static org.junit.Assert.assertTrue; 41 import static org.mockito.ArgumentMatchers.any; 42 import static org.mockito.ArgumentMatchers.anyBoolean; 43 import static org.mockito.ArgumentMatchers.anyInt; 44 import static org.mockito.ArgumentMatchers.anyLong; 45 import static org.mockito.ArgumentMatchers.anyString; 46 import static org.mockito.ArgumentMatchers.eq; 47 import static org.mockito.Mockito.mock; 48 import static org.mockito.Mockito.times; 49 import static org.mockito.Mockito.verify; 50 51 import android.app.servertransaction.ClientTransaction; 52 import android.app.servertransaction.RefreshCallbackItem; 53 import android.app.servertransaction.ResumeActivityItem; 54 import android.content.ComponentName; 55 import android.content.pm.ActivityInfo.ScreenOrientation; 56 import android.content.pm.ApplicationInfo; 57 import android.content.pm.PackageManager; 58 import android.content.res.Configuration; 59 import android.content.res.Configuration.Orientation; 60 import android.hardware.camera2.CameraManager; 61 import android.os.Handler; 62 import android.platform.test.annotations.Presubmit; 63 import android.view.Display; 64 import android.view.Surface.Rotation; 65 66 import androidx.test.filters.SmallTest; 67 68 import com.android.internal.R; 69 70 import org.junit.Before; 71 import org.junit.Test; 72 import org.junit.runner.RunWith; 73 74 import java.util.concurrent.Executor; 75 76 /** 77 * Tests for {@link DisplayRotationCompatPolicy}. 78 * 79 * Build/Install/Run: 80 * atest WmTests:DisplayRotationCompatPolicyTests 81 */ 82 @SmallTest 83 @Presubmit 84 @RunWith(WindowTestRunner.class) 85 public final class DisplayRotationCompatPolicyTests extends WindowTestsBase { 86 87 private static final String TEST_PACKAGE_1 = "com.test.package.one"; 88 private static final String TEST_PACKAGE_2 = "com.test.package.two"; 89 private static final String CAMERA_ID_1 = "camera-1"; 90 private static final String CAMERA_ID_2 = "camera-2"; 91 private static final String TEST_PACKAGE_1_LABEL = "testPackage1"; 92 private CameraManager mMockCameraManager; 93 private Handler mMockHandler; 94 private LetterboxConfiguration mLetterboxConfiguration; 95 96 private DisplayRotationCompatPolicy mDisplayRotationCompatPolicy; 97 private CameraManager.AvailabilityCallback mCameraAvailabilityCallback; 98 99 private ActivityRecord mActivity; 100 private Task mTask; 101 102 @Before setUp()103 public void setUp() throws Exception { 104 mLetterboxConfiguration = mDisplayContent.mWmService.mLetterboxConfiguration; 105 spyOn(mLetterboxConfiguration); 106 when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled()) 107 .thenReturn(true); 108 when(mLetterboxConfiguration.isCameraCompatRefreshEnabled()) 109 .thenReturn(true); 110 when(mLetterboxConfiguration.isCameraCompatRefreshCycleThroughStopEnabled()) 111 .thenReturn(true); 112 113 mMockCameraManager = mock(CameraManager.class); 114 doAnswer(invocation -> { 115 mCameraAvailabilityCallback = invocation.getArgument(1); 116 return null; 117 }).when(mMockCameraManager).registerAvailabilityCallback( 118 any(Executor.class), any(CameraManager.AvailabilityCallback.class)); 119 120 spyOn(mContext); 121 when(mContext.getSystemService(CameraManager.class)).thenReturn(mMockCameraManager); 122 123 spyOn(mDisplayContent); 124 125 mDisplayContent.setIgnoreOrientationRequest(true); 126 127 mMockHandler = mock(Handler.class); 128 129 when(mMockHandler.postDelayed(any(Runnable.class), anyLong())).thenAnswer( 130 invocation -> { 131 ((Runnable) invocation.getArgument(0)).run(); 132 return null; 133 }); 134 mDisplayRotationCompatPolicy = new DisplayRotationCompatPolicy( 135 mDisplayContent, mMockHandler); 136 } 137 138 @Test testOpenedCameraInSplitScreen_showToast()139 public void testOpenedCameraInSplitScreen_showToast() throws Exception { 140 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 141 spyOn(mTask); 142 spyOn(mDisplayRotationCompatPolicy); 143 doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode(); 144 doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mTask).getWindowingMode(); 145 146 final PackageManager mockPackageManager = mock(PackageManager.class); 147 final ApplicationInfo mockApplicationInfo = mock(ApplicationInfo.class); 148 when(mContext.getPackageManager()).thenReturn(mockPackageManager); 149 when(mockPackageManager.getApplicationInfo(anyString(), anyInt())) 150 .thenReturn(mockApplicationInfo); 151 152 doReturn(TEST_PACKAGE_1_LABEL).when(mockPackageManager) 153 .getApplicationLabel(mockApplicationInfo); 154 155 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 156 157 verify(mDisplayRotationCompatPolicy).showToast( 158 R.string.display_rotation_camera_compat_toast_in_multi_window, 159 TEST_PACKAGE_1_LABEL); 160 } 161 162 @Test testOpenedCameraInSplitScreen_orientationNotFixed_doNotShowToast()163 public void testOpenedCameraInSplitScreen_orientationNotFixed_doNotShowToast() { 164 configureActivity(SCREEN_ORIENTATION_UNSPECIFIED); 165 spyOn(mTask); 166 spyOn(mDisplayRotationCompatPolicy); 167 doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mActivity).getWindowingMode(); 168 doReturn(WINDOWING_MODE_MULTI_WINDOW).when(mTask).getWindowingMode(); 169 170 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 171 172 verify(mDisplayRotationCompatPolicy, never()).showToast( 173 R.string.display_rotation_camera_compat_toast_in_multi_window, 174 TEST_PACKAGE_1_LABEL); 175 } 176 177 @Test testOnScreenRotationAnimationFinished_treatmentNotEnabled_doNotShowToast()178 public void testOnScreenRotationAnimationFinished_treatmentNotEnabled_doNotShowToast() { 179 when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled()) 180 .thenReturn(false); 181 spyOn(mDisplayRotationCompatPolicy); 182 183 mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished(); 184 185 verify(mDisplayRotationCompatPolicy, never()).showToast( 186 R.string.display_rotation_camera_compat_toast_after_rotation); 187 } 188 189 @Test testOnScreenRotationAnimationFinished_noOpenCamera_doNotShowToast()190 public void testOnScreenRotationAnimationFinished_noOpenCamera_doNotShowToast() { 191 spyOn(mDisplayRotationCompatPolicy); 192 193 mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished(); 194 195 verify(mDisplayRotationCompatPolicy, never()).showToast( 196 R.string.display_rotation_camera_compat_toast_after_rotation); 197 } 198 199 @Test testOnScreenRotationAnimationFinished_notFullscreen_doNotShowToast()200 public void testOnScreenRotationAnimationFinished_notFullscreen_doNotShowToast() { 201 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 202 doReturn(true).when(mActivity).inMultiWindowMode(); 203 spyOn(mDisplayRotationCompatPolicy); 204 205 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 206 207 mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished(); 208 209 verify(mDisplayRotationCompatPolicy, never()).showToast( 210 R.string.display_rotation_camera_compat_toast_after_rotation); 211 } 212 213 @Test testOnScreenRotationAnimationFinished_orientationNotFixed_doNotShowToast()214 public void testOnScreenRotationAnimationFinished_orientationNotFixed_doNotShowToast() { 215 configureActivity(SCREEN_ORIENTATION_UNSPECIFIED); 216 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 217 spyOn(mDisplayRotationCompatPolicy); 218 219 mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished(); 220 221 verify(mDisplayRotationCompatPolicy, never()).showToast( 222 R.string.display_rotation_camera_compat_toast_after_rotation); 223 } 224 225 @Test testOnScreenRotationAnimationFinished_showToast()226 public void testOnScreenRotationAnimationFinished_showToast() { 227 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 228 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 229 spyOn(mDisplayRotationCompatPolicy); 230 231 mDisplayRotationCompatPolicy.onScreenRotationAnimationFinished(); 232 233 verify(mDisplayRotationCompatPolicy).showToast( 234 R.string.display_rotation_camera_compat_toast_after_rotation); 235 } 236 237 @Test testTreatmentNotEnabled_noForceRotationOrRefresh()238 public void testTreatmentNotEnabled_noForceRotationOrRefresh() throws Exception { 239 when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled()) 240 .thenReturn(false); 241 242 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 243 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 244 245 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 246 SCREEN_ORIENTATION_UNSPECIFIED); 247 248 assertNoForceRotationOrRefresh(); 249 } 250 251 @Test testTreatmentDisabledViaDeviceConfig_noForceRotationOrRefresh()252 public void testTreatmentDisabledViaDeviceConfig_noForceRotationOrRefresh() throws Exception { 253 when(mLetterboxConfiguration.isCameraCompatTreatmentEnabled()) 254 .thenReturn(false); 255 256 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 257 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 258 259 assertNoForceRotationOrRefresh(); 260 } 261 262 @Test testTreatmentDisabledPerApp_noForceRotationOrRefresh()263 public void testTreatmentDisabledPerApp_noForceRotationOrRefresh() 264 throws Exception { 265 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 266 when(mActivity.mLetterboxUiController.shouldForceRotateForCameraCompat()) 267 .thenReturn(false); 268 269 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 270 271 assertNoForceRotationOrRefresh(); 272 } 273 274 @Test testMultiWindowMode_returnUnspecified_noForceRotationOrRefresh()275 public void testMultiWindowMode_returnUnspecified_noForceRotationOrRefresh() throws Exception { 276 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 277 final TestSplitOrganizer organizer = new TestSplitOrganizer(mAtm, mDisplayContent); 278 mActivity.getTask().reparent(organizer.mPrimary, WindowContainer.POSITION_TOP, 279 false /* moveParents */, "test" /* reason */); 280 281 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 282 283 assertTrue(mActivity.inMultiWindowMode()); 284 assertNoForceRotationOrRefresh(); 285 } 286 287 @Test testOrientationUnspecified_noForceRotationOrRefresh()288 public void testOrientationUnspecified_noForceRotationOrRefresh() throws Exception { 289 configureActivity(SCREEN_ORIENTATION_UNSPECIFIED); 290 291 assertNoForceRotationOrRefresh(); 292 } 293 294 @Test testOrientationLocked_noForceRotationOrRefresh()295 public void testOrientationLocked_noForceRotationOrRefresh() throws Exception { 296 configureActivity(SCREEN_ORIENTATION_LOCKED); 297 298 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 299 300 assertNoForceRotationOrRefresh(); 301 } 302 303 @Test testOrientationNoSensor_noForceRotationOrRefresh()304 public void testOrientationNoSensor_noForceRotationOrRefresh() throws Exception { 305 configureActivity(SCREEN_ORIENTATION_NOSENSOR); 306 307 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 308 309 assertNoForceRotationOrRefresh(); 310 } 311 312 @Test testIgnoreOrientationRequestIsFalse_noForceRotationOrRefresh()313 public void testIgnoreOrientationRequestIsFalse_noForceRotationOrRefresh() throws Exception { 314 mDisplayContent.setIgnoreOrientationRequest(false); 315 316 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 317 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 318 319 assertNoForceRotationOrRefresh(); 320 } 321 322 @Test testDisplayNotInternal_noForceRotationOrRefresh()323 public void testDisplayNotInternal_noForceRotationOrRefresh() throws Exception { 324 Display display = mDisplayContent.getDisplay(); 325 spyOn(display); 326 327 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 328 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 329 330 when(display.getType()).thenReturn(Display.TYPE_EXTERNAL); 331 assertNoForceRotationOrRefresh(); 332 333 when(display.getType()).thenReturn(Display.TYPE_WIFI); 334 assertNoForceRotationOrRefresh(); 335 336 when(display.getType()).thenReturn(Display.TYPE_OVERLAY); 337 assertNoForceRotationOrRefresh(); 338 339 when(display.getType()).thenReturn(Display.TYPE_VIRTUAL); 340 assertNoForceRotationOrRefresh(); 341 } 342 343 @Test testNoCameraConnection_noForceRotationOrRefresh()344 public void testNoCameraConnection_noForceRotationOrRefresh() throws Exception { 345 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 346 347 assertNoForceRotationOrRefresh(); 348 } 349 350 @Test testCameraReconnected_forceRotationAndRefresh()351 public void testCameraReconnected_forceRotationAndRefresh() throws Exception { 352 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 353 354 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 355 mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); 356 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 357 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 358 359 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 360 SCREEN_ORIENTATION_PORTRAIT); 361 assertActivityRefreshRequested(/* refreshRequested */ true); 362 } 363 364 @Test testReconnectedToDifferentCamera_forceRotationAndRefresh()365 public void testReconnectedToDifferentCamera_forceRotationAndRefresh() throws Exception { 366 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 367 368 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 369 mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); 370 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_2, TEST_PACKAGE_1); 371 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 372 373 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 374 SCREEN_ORIENTATION_PORTRAIT); 375 assertActivityRefreshRequested(/* refreshRequested */ true); 376 } 377 378 @Test testCameraDisconnected_revertRotationAndRefresh()379 public void testCameraDisconnected_revertRotationAndRefresh() throws Exception { 380 configureActivityAndDisplay(SCREEN_ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE); 381 // Open camera and test for compat treatment 382 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 383 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 384 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 385 SCREEN_ORIENTATION_LANDSCAPE); 386 assertActivityRefreshRequested(/* refreshRequested */ true); 387 // Close camera and test for revert 388 mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); 389 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 390 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 391 SCREEN_ORIENTATION_UNSPECIFIED); 392 assertActivityRefreshRequested(/* refreshRequested */ true); 393 } 394 395 @Test testGetOrientation_cameraConnectionClosed_returnUnspecified()396 public void testGetOrientation_cameraConnectionClosed_returnUnspecified() { 397 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 398 399 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 400 401 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 402 SCREEN_ORIENTATION_PORTRAIT); 403 404 mCameraAvailabilityCallback.onCameraClosed(CAMERA_ID_1); 405 406 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 407 SCREEN_ORIENTATION_UNSPECIFIED); 408 } 409 410 @Test testCameraOpenedForDifferentPackage_noForceRotationOrRefresh()411 public void testCameraOpenedForDifferentPackage_noForceRotationOrRefresh() throws Exception { 412 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 413 414 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_2); 415 416 assertNoForceRotationOrRefresh(); 417 } 418 419 @Test testGetOrientation_portraitActivity_portraitNaturalOrientation_returnPortrait()420 public void testGetOrientation_portraitActivity_portraitNaturalOrientation_returnPortrait() { 421 testGetOrientationForActivityAndNaturalOrientations( 422 /* activityOrientation */ SCREEN_ORIENTATION_PORTRAIT, 423 /* naturalOrientation */ ORIENTATION_PORTRAIT, 424 /* expectedOrientation */ SCREEN_ORIENTATION_PORTRAIT); 425 } 426 427 @Test testGetOrientation_portraitActivity_landscapeNaturalOrientation_returnLandscape()428 public void testGetOrientation_portraitActivity_landscapeNaturalOrientation_returnLandscape() { 429 testGetOrientationForActivityAndNaturalOrientations( 430 /* activityOrientation */ SCREEN_ORIENTATION_PORTRAIT, 431 /* naturalOrientation */ ORIENTATION_LANDSCAPE, 432 /* expectedOrientation */ SCREEN_ORIENTATION_LANDSCAPE); 433 } 434 435 @Test testGetOrientation_landscapeActivity_portraitNaturalOrientation_returnLandscape()436 public void testGetOrientation_landscapeActivity_portraitNaturalOrientation_returnLandscape() { 437 testGetOrientationForActivityAndNaturalOrientations( 438 /* activityOrientation */ SCREEN_ORIENTATION_LANDSCAPE, 439 /* naturalOrientation */ ORIENTATION_PORTRAIT, 440 /* expectedOrientation */ SCREEN_ORIENTATION_LANDSCAPE); 441 } 442 443 @Test testGetOrientation_landscapeActivity_landscapeNaturalOrientation_returnPortrait()444 public void testGetOrientation_landscapeActivity_landscapeNaturalOrientation_returnPortrait() { 445 testGetOrientationForActivityAndNaturalOrientations( 446 /* activityOrientation */ SCREEN_ORIENTATION_LANDSCAPE, 447 /* naturalOrientation */ ORIENTATION_LANDSCAPE, 448 /* expectedOrientation */ SCREEN_ORIENTATION_PORTRAIT); 449 } 450 testGetOrientationForActivityAndNaturalOrientations( @creenOrientation int activityOrientation, @Orientation int naturalOrientation, @ScreenOrientation int expectedOrientation)451 private void testGetOrientationForActivityAndNaturalOrientations( 452 @ScreenOrientation int activityOrientation, 453 @Orientation int naturalOrientation, 454 @ScreenOrientation int expectedOrientation) { 455 configureActivityAndDisplay(activityOrientation, naturalOrientation); 456 457 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 458 459 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 460 expectedOrientation); 461 } 462 463 @Test testOnActivityConfigurationChanging_refreshDisabledViaFlag_noRefresh()464 public void testOnActivityConfigurationChanging_refreshDisabledViaFlag_noRefresh() 465 throws Exception { 466 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 467 when(mActivity.mLetterboxUiController.shouldRefreshActivityForCameraCompat()) 468 .thenReturn(false); 469 470 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 471 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 472 473 assertActivityRefreshRequested(/* refreshRequested */ false); 474 } 475 476 @Test testOnActivityConfigurationChanging_refreshDisabledPerApp_noRefresh()477 public void testOnActivityConfigurationChanging_refreshDisabledPerApp_noRefresh() 478 throws Exception { 479 when(mLetterboxConfiguration.isCameraCompatRefreshEnabled()).thenReturn(false); 480 481 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 482 483 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 484 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 485 486 assertActivityRefreshRequested(/* refreshRequested */ false); 487 } 488 489 @Test testOnActivityConfigurationChanging_displayRotationNotChanging_noRefresh()490 public void testOnActivityConfigurationChanging_displayRotationNotChanging_noRefresh() 491 throws Exception { 492 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 493 doReturn(false).when(mActivity.mLetterboxUiController) 494 .isCameraCompatSplitScreenAspectRatioAllowed(); 495 496 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 497 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ false); 498 499 assertActivityRefreshRequested(/* refreshRequested */ false); 500 } 501 502 @Test testOnActivityConfigurationChanging_splitScreenAspectRatioAllowed_refresh()503 public void testOnActivityConfigurationChanging_splitScreenAspectRatioAllowed_refresh() 504 throws Exception { 505 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 506 doReturn(true).when(mActivity.mLetterboxUiController) 507 .isCameraCompatSplitScreenAspectRatioAllowed(); 508 509 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 510 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ false); 511 512 assertActivityRefreshRequested(/* refreshRequested */ true); 513 } 514 515 @Test testOnActivityConfigurationChanging_cycleThroughStopDisabled()516 public void testOnActivityConfigurationChanging_cycleThroughStopDisabled() throws Exception { 517 when(mLetterboxConfiguration.isCameraCompatRefreshCycleThroughStopEnabled()) 518 .thenReturn(false); 519 520 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 521 522 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 523 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 524 525 assertActivityRefreshRequested(/* refreshRequested */ true, /* cycleThroughStop */ false); 526 } 527 528 @Test testOnActivityConfigurationChanging_cycleThroughStopDisabledForApp()529 public void testOnActivityConfigurationChanging_cycleThroughStopDisabledForApp() 530 throws Exception { 531 configureActivity(SCREEN_ORIENTATION_PORTRAIT); 532 when(mActivity.mLetterboxUiController.shouldRefreshActivityViaPauseForCameraCompat()) 533 .thenReturn(true); 534 535 mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1); 536 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 537 538 assertActivityRefreshRequested(/* refreshRequested */ true, /* cycleThroughStop */ false); 539 } 540 configureActivity(@creenOrientation int activityOrientation)541 private void configureActivity(@ScreenOrientation int activityOrientation) { 542 configureActivityAndDisplay(activityOrientation, ORIENTATION_PORTRAIT); 543 } 544 configureActivityAndDisplay(@creenOrientation int activityOrientation, @Orientation int naturalOrientation)545 private void configureActivityAndDisplay(@ScreenOrientation int activityOrientation, 546 @Orientation int naturalOrientation) { 547 548 mTask = new TaskBuilder(mSupervisor) 549 .setDisplay(mDisplayContent) 550 .build(); 551 552 mActivity = new ActivityBuilder(mAtm) 553 .setComponent(new ComponentName(TEST_PACKAGE_1, ".TestActivity")) 554 .setScreenOrientation(activityOrientation) 555 .setTask(mTask) 556 .build(); 557 558 spyOn(mActivity.mAtmService.getLifecycleManager()); 559 spyOn(mActivity.mLetterboxUiController); 560 561 doReturn(mActivity).when(mDisplayContent).topRunningActivity(anyBoolean()); 562 doReturn(naturalOrientation).when(mDisplayContent).getNaturalOrientation(); 563 } 564 assertActivityRefreshRequested(boolean refreshRequested)565 private void assertActivityRefreshRequested(boolean refreshRequested) throws Exception { 566 assertActivityRefreshRequested(refreshRequested, /* cycleThroughStop*/ true); 567 } 568 assertActivityRefreshRequested(boolean refreshRequested, boolean cycleThroughStop)569 private void assertActivityRefreshRequested(boolean refreshRequested, 570 boolean cycleThroughStop) throws Exception { 571 verify(mActivity.mLetterboxUiController, times(refreshRequested ? 1 : 0)) 572 .setIsRefreshAfterRotationRequested(true); 573 574 final ClientTransaction transaction = ClientTransaction.obtain( 575 mActivity.app.getThread(), mActivity.token); 576 transaction.addCallback(RefreshCallbackItem.obtain(cycleThroughStop ? ON_STOP : ON_PAUSE)); 577 transaction.setLifecycleStateRequest(ResumeActivityItem.obtain( 578 /* isForward */ false, /* shouldSendCompatFakeFocus */ false)); 579 580 verify(mActivity.mAtmService.getLifecycleManager(), times(refreshRequested ? 1 : 0)) 581 .scheduleTransaction(eq(transaction)); 582 } 583 assertNoForceRotationOrRefresh()584 private void assertNoForceRotationOrRefresh() throws Exception { 585 callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true); 586 587 assertEquals(mDisplayRotationCompatPolicy.getOrientation(), 588 SCREEN_ORIENTATION_UNSPECIFIED); 589 assertActivityRefreshRequested(/* refreshRequested */ false); 590 } 591 callOnActivityConfigurationChanging( ActivityRecord activity, boolean isDisplayRotationChanging)592 private void callOnActivityConfigurationChanging( 593 ActivityRecord activity, boolean isDisplayRotationChanging) { 594 mDisplayRotationCompatPolicy.onActivityConfigurationChanging(activity, 595 /* newConfig */ createConfigurationWithDisplayRotation(ROTATION_0), 596 /* newConfig */ createConfigurationWithDisplayRotation( 597 isDisplayRotationChanging ? ROTATION_90 : ROTATION_0)); 598 } 599 createConfigurationWithDisplayRotation(@otation int rotation)600 private static Configuration createConfigurationWithDisplayRotation(@Rotation int rotation) { 601 final Configuration config = new Configuration(); 602 config.windowConfiguration.setDisplayRotation(rotation); 603 return config; 604 } 605 } 606