1 /* 2 * Copyright (C) 2018 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.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; 20 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED; 21 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; 22 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; 23 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR; 24 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 25 import static android.view.DisplayCutout.NO_CUTOUT; 26 import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DEFAULT; 27 import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_DISABLED; 28 import static android.view.IWindowManager.FIXED_TO_USER_ROTATION_ENABLED; 29 30 import static com.android.dx.mockito.inline.extended.ExtendedMockito.any; 31 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; 32 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyInt; 33 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast; 34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atMost; 35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 36 import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq; 37 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock; 38 import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset; 39 import static com.android.dx.mockito.inline.extended.ExtendedMockito.same; 40 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; 41 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; 42 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when; 43 44 import static org.junit.Assert.assertEquals; 45 import static org.junit.Assert.assertFalse; 46 import static org.junit.Assert.assertTrue; 47 import static org.mockito.Mockito.clearInvocations; 48 49 import android.app.WindowConfiguration; 50 import android.content.ContentResolver; 51 import android.content.Context; 52 import android.content.Intent; 53 import android.content.pm.ActivityInfo; 54 import android.content.pm.PackageManager; 55 import android.content.res.Resources; 56 import android.database.ContentObserver; 57 import android.hardware.Sensor; 58 import android.hardware.SensorEvent; 59 import android.hardware.SensorEventListener; 60 import android.hardware.SensorManager; 61 import android.hardware.devicestate.DeviceStateManager; 62 import android.os.Handler; 63 import android.os.IBinder; 64 import android.os.PowerManagerInternal; 65 import android.os.SystemClock; 66 import android.platform.test.annotations.Presubmit; 67 import android.provider.Settings; 68 import android.view.DisplayAddress; 69 import android.view.IRotationWatcher; 70 import android.view.Surface; 71 import android.view.WindowManager; 72 73 import androidx.annotation.Nullable; 74 import androidx.test.filters.SmallTest; 75 76 import com.android.internal.R; 77 import com.android.internal.util.test.FakeSettingsProvider; 78 import com.android.server.LocalServices; 79 import com.android.server.UiThread; 80 import com.android.server.policy.WindowManagerPolicy; 81 import com.android.server.statusbar.StatusBarManagerInternal; 82 import com.android.server.testutils.OffsettableClock; 83 import com.android.server.testutils.TestHandler; 84 import com.android.server.wm.DisplayContent.FixedRotationTransitionListener; 85 86 import org.junit.After; 87 import org.junit.AfterClass; 88 import org.junit.Before; 89 import org.junit.BeforeClass; 90 import org.junit.Test; 91 import org.mockito.ArgumentCaptor; 92 93 import java.lang.reflect.Constructor; 94 import java.lang.reflect.Field; 95 import java.lang.reflect.Method; 96 import java.util.Collections; 97 import java.util.concurrent.CountDownLatch; 98 import java.util.concurrent.TimeUnit; 99 import java.util.function.IntConsumer; 100 101 /** 102 * Test class for {@link DisplayRotation}. 103 * 104 * Build/Install/Run: 105 * atest WmTests:DisplayRotationTests 106 */ 107 @SmallTest 108 @Presubmit 109 public class DisplayRotationTests { 110 private static final long UI_HANDLER_WAIT_TIMEOUT_MS = 50; 111 112 private StatusBarManagerInternal mPreviousStatusBarManagerInternal; 113 private static final OffsettableClock sClock = new OffsettableClock.Stopped(); 114 private static TestHandler sHandler; 115 private static long sCurrentUptimeMillis = 10_000; 116 117 private static WindowManagerService sMockWm; 118 private DisplayContent mMockDisplayContent; 119 private DisplayRotationReversionController mMockDisplayRotationReversionController; 120 private DisplayPolicy mMockDisplayPolicy; 121 private DisplayAddress mMockDisplayAddress; 122 private Context mMockContext; 123 private Resources mMockRes; 124 private SensorManager mMockSensorManager; 125 private Sensor mFakeOrientationSensor; 126 private Sensor mFakeHingeAngleSensor; 127 private DisplayWindowSettings mMockDisplayWindowSettings; 128 private ContentResolver mMockResolver; 129 private FakeSettingsProvider mFakeSettingsProvider; 130 private StatusBarManagerInternal mMockStatusBarManagerInternal; 131 private DeviceStateManager mMockDeviceStateManager; 132 133 // Fields below are callbacks captured from test target. 134 private ContentObserver mShowRotationSuggestionsObserver; 135 private ContentObserver mAccelerometerRotationObserver; 136 private ContentObserver mUserRotationObserver; 137 private SensorEventListener mOrientationSensorListener; 138 139 ArgumentCaptor<SensorEventListener> mHingeAngleSensorListenerCaptor = ArgumentCaptor.forClass( 140 SensorEventListener.class); 141 142 private DisplayRotationBuilder mBuilder; 143 144 private DeviceStateController mDeviceStateController; 145 private TestDisplayRotation mTarget; 146 @Nullable 147 private DisplayRotationImmersiveAppCompatPolicy mDisplayRotationImmersiveAppCompatPolicyMock; 148 149 @BeforeClass setUpOnce()150 public static void setUpOnce() { 151 sMockWm = mock(WindowManagerService.class); 152 sMockWm.mPowerManagerInternal = mock(PowerManagerInternal.class); 153 sMockWm.mPolicy = mock(WindowManagerPolicy.class); 154 sHandler = new TestHandler(null, sClock); 155 } 156 157 @AfterClass tearDownOnce()158 public static void tearDownOnce() { 159 sMockWm = null; 160 // Make sure the fake settings are cleared after the last test method. 161 FakeSettingsProvider.clearSettingsProvider(); 162 } 163 164 @Before setUp()165 public void setUp() { 166 FakeSettingsProvider.clearSettingsProvider(); 167 168 mPreviousStatusBarManagerInternal = LocalServices.getService( 169 StatusBarManagerInternal.class); 170 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 171 mMockStatusBarManagerInternal = mock(StatusBarManagerInternal.class); 172 LocalServices.addService(StatusBarManagerInternal.class, mMockStatusBarManagerInternal); 173 mDisplayRotationImmersiveAppCompatPolicyMock = null; 174 mBuilder = new DisplayRotationBuilder(); 175 } 176 177 @After tearDown()178 public void tearDown() { 179 LocalServices.removeServiceForTest(StatusBarManagerInternal.class); 180 if (mPreviousStatusBarManagerInternal != null) { 181 LocalServices.addService(StatusBarManagerInternal.class, 182 mPreviousStatusBarManagerInternal); 183 mPreviousStatusBarManagerInternal = null; 184 } 185 } 186 187 // ================================ 188 // Display Settings Related Tests 189 // ================================ 190 @Test testLocksUserRotation_LockRotation_DefaultDisplay()191 public void testLocksUserRotation_LockRotation_DefaultDisplay() throws Exception { 192 mBuilder.build(); 193 194 freezeRotation(Surface.ROTATION_180); 195 196 assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode()); 197 assertEquals(Surface.ROTATION_180, mTarget.getUserRotation()); 198 199 assertEquals(0, Settings.System.getInt(mMockResolver, 200 Settings.System.ACCELEROMETER_ROTATION)); 201 assertEquals(Surface.ROTATION_180, Settings.System.getInt(mMockResolver, 202 Settings.System.USER_ROTATION)); 203 } 204 205 @Test testPersistsUserRotation_LockRotation_NonDefaultDisplay()206 public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception { 207 mBuilder.setIsDefaultDisplay(false).build(); 208 209 freezeRotation(Surface.ROTATION_180); 210 211 assertEquals(WindowManagerPolicy.USER_ROTATION_LOCKED, mTarget.getUserRotationMode()); 212 assertEquals(Surface.ROTATION_180, mTarget.getUserRotation()); 213 214 verify(mMockDisplayWindowSettings).setUserRotation(mMockDisplayContent, 215 WindowManagerPolicy.USER_ROTATION_LOCKED, Surface.ROTATION_180); 216 } 217 218 @Test testPersistUserRotation_UnlockRotation_DefaultDisplay()219 public void testPersistUserRotation_UnlockRotation_DefaultDisplay() throws Exception { 220 mBuilder.build(); 221 222 thawRotation(); 223 224 assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode()); 225 226 assertEquals(1, Settings.System.getInt(mMockResolver, 227 Settings.System.ACCELEROMETER_ROTATION)); 228 } 229 230 @Test testPersistsUserRotation_UnlockRotation_NonDefaultDisplay()231 public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception { 232 mBuilder.setIsDefaultDisplay(false).build(); 233 234 thawRotation(); 235 236 assertEquals(WindowManagerPolicy.USER_ROTATION_FREE, mTarget.getUserRotationMode()); 237 238 verify(mMockDisplayWindowSettings).setUserRotation(same(mMockDisplayContent), 239 eq(WindowManagerPolicy.USER_ROTATION_FREE), anyInt()); 240 } 241 242 @Test testPersistsFixedToUserRotation()243 public void testPersistsFixedToUserRotation() throws Exception { 244 mBuilder.build(); 245 246 mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); 247 248 verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, 249 FIXED_TO_USER_ROTATION_ENABLED); 250 251 reset(mMockDisplayWindowSettings); 252 mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DISABLED); 253 254 verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, 255 FIXED_TO_USER_ROTATION_DISABLED); 256 257 reset(mMockDisplayWindowSettings); 258 mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DEFAULT); 259 260 verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, 261 FIXED_TO_USER_ROTATION_DEFAULT); 262 } 263 264 // ======================================== 265 // Tests for User Rotation based Rotation 266 // ======================================== 267 @Test testReturnsUserRotation_UserRotationLocked_NoAppRequest()268 public void testReturnsUserRotation_UserRotationLocked_NoAppRequest() 269 throws Exception { 270 mBuilder.build(); 271 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 272 273 freezeRotation(Surface.ROTATION_180); 274 275 assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( 276 ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90)); 277 } 278 279 @Test testReturnsLandscape_UserRotationLockedSeascape_AppRequestsLandscape()280 public void testReturnsLandscape_UserRotationLockedSeascape_AppRequestsLandscape() 281 throws Exception { 282 mBuilder.build(); 283 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false /* isCar */, 284 false /* isTv */); 285 286 freezeRotation(Surface.ROTATION_180); 287 288 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 289 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90)); 290 } 291 292 @Test testReturnsSeascape_UserRotationLockedSeascape_AppRequestsSeascape()293 public void testReturnsSeascape_UserRotationLockedSeascape_AppRequestsSeascape() 294 throws Exception { 295 mBuilder.build(); 296 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false /* isCar */, 297 false /* isTv */); 298 299 freezeRotation(Surface.ROTATION_180); 300 301 assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( 302 ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE, Surface.ROTATION_90)); 303 } 304 305 @Test testReturnsPortrait_UserRotationLockedPortrait_AppRequestsPortrait()306 public void testReturnsPortrait_UserRotationLockedPortrait_AppRequestsPortrait() 307 throws Exception { 308 mBuilder.build(); 309 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false /* isCar */, 310 false /* isTv */); 311 312 freezeRotation(Surface.ROTATION_270); 313 314 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 315 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_0)); 316 } 317 318 @Test testReturnsUpsideDown_UserRotationLockedUpsideDown_AppRequestsUpsideDown()319 public void testReturnsUpsideDown_UserRotationLockedUpsideDown_AppRequestsUpsideDown() 320 throws Exception { 321 mBuilder.build(); 322 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false /* isCar */, 323 false /* isTv */); 324 325 freezeRotation(Surface.ROTATION_90); 326 327 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 328 ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT, Surface.ROTATION_0)); 329 } 330 331 @Test testReturnsSideways_UserRotationLocked_IncompatibleAppRequest()332 public void testReturnsSideways_UserRotationLocked_IncompatibleAppRequest() 333 throws Exception { 334 mBuilder.build(); 335 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 336 337 freezeRotation(Surface.ROTATION_180); 338 339 final int rotation = mTarget.rotationForOrientation( 340 ActivityInfo.SCREEN_ORIENTATION_PORTRAIT, Surface.ROTATION_90); 341 assertTrue("Rotation should be sideways, but it's " 342 + Surface.rotationToString(rotation), 343 rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270); 344 } 345 346 // ================================= 347 // Tests for Sensor based Rotation 348 // ================================= verifyOrientationListenerRegistration(int numOfInvocation)349 private void verifyOrientationListenerRegistration(int numOfInvocation) { 350 final ArgumentCaptor<SensorEventListener> listenerCaptor = ArgumentCaptor.forClass( 351 SensorEventListener.class); 352 waitForUiHandler(); 353 verify(mMockSensorManager, times(numOfInvocation)).registerListener( 354 listenerCaptor.capture(), 355 same(mFakeOrientationSensor), 356 anyInt(), 357 any()); 358 if (numOfInvocation > 0) { 359 mOrientationSensorListener = listenerCaptor.getValue(); 360 } 361 } 362 363 @Test testNotEnablesSensor_AutoRotationNotSupported()364 public void testNotEnablesSensor_AutoRotationNotSupported() throws Exception { 365 mBuilder.setSupportAutoRotation(false).build(); 366 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 367 368 thawRotation(); 369 370 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 371 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 372 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 373 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 374 mTarget.updateOrientationListener(); 375 verifyOrientationListenerRegistration(0); 376 } 377 378 @Test testNotEnablesSensor_ScreenNotOn()379 public void testNotEnablesSensor_ScreenNotOn() throws Exception { 380 mBuilder.build(); 381 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 382 383 thawRotation(); 384 385 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(false); 386 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 387 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 388 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 389 mTarget.updateOrientationListener(); 390 verifyOrientationListenerRegistration(0); 391 } 392 393 @Test testNotEnablesSensor_NotAwake()394 public void testNotEnablesSensor_NotAwake() throws Exception { 395 mBuilder.build(); 396 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 397 398 thawRotation(); 399 400 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 401 when(mMockDisplayPolicy.isAwake()).thenReturn(false); 402 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 403 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 404 mTarget.updateOrientationListener(); 405 verifyOrientationListenerRegistration(0); 406 } 407 408 @Test testNotEnablesSensor_KeyguardNotDrawnCompletely()409 public void testNotEnablesSensor_KeyguardNotDrawnCompletely() throws Exception { 410 mBuilder.build(); 411 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 412 413 thawRotation(); 414 415 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 416 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 417 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(false); 418 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 419 mTarget.updateOrientationListener(); 420 verifyOrientationListenerRegistration(0); 421 } 422 423 @Test testNotEnablesSensor_WindowManagerNotDrawnCompletely()424 public void testNotEnablesSensor_WindowManagerNotDrawnCompletely() throws Exception { 425 mBuilder.build(); 426 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 427 428 thawRotation(); 429 430 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 431 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 432 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 433 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(false); 434 mTarget.updateOrientationListener(); 435 verifyOrientationListenerRegistration(0); 436 } 437 438 @Test testNotEnablesSensor_FixedUserRotation()439 public void testNotEnablesSensor_FixedUserRotation() throws Exception { 440 mBuilder.build(); 441 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 442 443 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 444 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 445 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 446 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 447 mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); 448 mTarget.updateOrientationListener(); 449 verifyOrientationListenerRegistration(0); 450 } 451 452 @Test testNotEnablesSensor_ForceDefaultRotation_Car()453 public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception { 454 mBuilder.build(); 455 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false); 456 457 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 458 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 459 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 460 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 461 mTarget.updateOrientationListener(); 462 verifyOrientationListenerRegistration(0); 463 } 464 465 @Test testNotEnablesSensor_ForceDefaultRotation_Tv()466 public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception { 467 mBuilder.build(); 468 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true); 469 470 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 471 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 472 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 473 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 474 mTarget.updateOrientationListener(); 475 verifyOrientationListenerRegistration(0); 476 } 477 enableOrientationSensor()478 private void enableOrientationSensor() { 479 when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true); 480 when(mMockDisplayPolicy.isAwake()).thenReturn(true); 481 when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true); 482 when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true); 483 mTarget.updateOrientationListener(); 484 verifyOrientationListenerRegistration(1); 485 } 486 createSensorEvent(int rotation)487 private SensorEvent createSensorEvent(int rotation) throws Exception { 488 return createSensorEvent(mFakeOrientationSensor, rotation); 489 } 490 createSensorEvent(Sensor sensor, int value)491 private SensorEvent createSensorEvent(Sensor sensor, int value) throws Exception { 492 final Constructor<SensorEvent> constructor = 493 SensorEvent.class.getDeclaredConstructor(int.class); 494 constructor.setAccessible(true); 495 final SensorEvent event = constructor.newInstance(1); 496 event.sensor = sensor; 497 event.values[0] = value; 498 event.timestamp = SystemClock.elapsedRealtimeNanos(); 499 return event; 500 } 501 502 @Test testReturnsSensorRotation_RotationThawed()503 public void testReturnsSensorRotation_RotationThawed() throws Exception { 504 mBuilder.build(); 505 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 506 507 thawRotation(); 508 509 enableOrientationSensor(); 510 511 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 512 513 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 514 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 515 } 516 517 @Test testReverseRotation()518 public void testReverseRotation() throws Exception { 519 mBuilder.build(); 520 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 521 522 when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mMockDisplayContent)) 523 .thenReturn(true); 524 525 thawRotation(); 526 527 enableOrientationSensor(); 528 529 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 530 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 531 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 532 533 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_270)); 534 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 535 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 536 537 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0)); 538 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 539 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 540 541 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 542 assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( 543 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_180)); 544 } 545 546 @Test testFreezeRotation_reverseRotationDirectionAroundZAxis_yes()547 public void testFreezeRotation_reverseRotationDirectionAroundZAxis_yes() throws Exception { 548 mBuilder.build(); 549 when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mMockDisplayContent)) 550 .thenReturn(true); 551 552 freezeRotation(Surface.ROTATION_90); 553 assertEquals(Surface.ROTATION_270, mTarget.getUserRotation()); 554 } 555 556 @Test testFreezeRotation_reverseRotationDirectionAroundZAxis_no()557 public void testFreezeRotation_reverseRotationDirectionAroundZAxis_no() throws Exception { 558 mBuilder.build(); 559 when(mDeviceStateController.shouldReverseRotationDirectionAroundZAxis(mMockDisplayContent)) 560 .thenReturn(false); 561 562 freezeRotation(Surface.ROTATION_90); 563 assertEquals(Surface.ROTATION_90, mTarget.getUserRotation()); 564 } 565 waitForUiHandler()566 private boolean waitForUiHandler() { 567 final CountDownLatch latch = new CountDownLatch(1); 568 UiThread.getHandler().post(latch::countDown); 569 try { 570 return latch.await(UI_HANDLER_WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS); 571 } catch (InterruptedException ignored) { 572 } 573 throw new AssertionError("Failed to wait for ui handler"); 574 } 575 576 @Test testUpdatesRotationWhenSensorUpdates_RotationThawed()577 public void testUpdatesRotationWhenSensorUpdates_RotationThawed() throws Exception { 578 mBuilder.build(); 579 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 580 581 thawRotation(); 582 583 enableOrientationSensor(); 584 585 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 586 assertTrue(waitForUiHandler()); 587 588 verify(sMockWm).updateRotation(false, false); 589 } 590 591 @Test testNotifiesChoiceWhenSensorUpdates_RotationLocked()592 public void testNotifiesChoiceWhenSensorUpdates_RotationLocked() throws Exception { 593 mBuilder.build(); 594 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 595 596 freezeRotation(Surface.ROTATION_270); 597 598 enableOrientationSensor(); 599 600 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 601 assertTrue(waitForUiHandler()); 602 603 verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true); 604 } 605 606 @Test testNotifiesChoiceWhenSensorUpdates_immersiveApp()607 public void testNotifiesChoiceWhenSensorUpdates_immersiveApp() throws Exception { 608 mDisplayRotationImmersiveAppCompatPolicyMock = mock( 609 DisplayRotationImmersiveAppCompatPolicy.class); 610 when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced( 611 Surface.ROTATION_90)).thenReturn(true); 612 613 mBuilder.build(); 614 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 615 616 thawRotation(); 617 618 enableOrientationSensor(); 619 620 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 621 assertTrue(waitForUiHandler()); 622 623 verify(mMockStatusBarManagerInternal).onProposedRotationChanged(Surface.ROTATION_90, true); 624 625 // An imaginary ActivityRecord.setRequestedOrientation call disables immersive mode: 626 when(mDisplayRotationImmersiveAppCompatPolicyMock.isRotationLockEnforced( 627 Surface.ROTATION_90)).thenReturn(false); 628 629 // And then ActivityRecord.setRequestedOrientation calls onSetRequestedOrientation. 630 mTarget.onSetRequestedOrientation(); 631 632 // onSetRequestedOrientation should lead to a second call to 633 // mOrientationListener.onProposedRotationChanged 634 // but now, instead of notifying mMockStatusBarManagerInternal, it calls updateRotation: 635 verify(sMockWm).updateRotation(false, false); 636 } 637 638 @Test testAllowAllRotations_allowsUpsideDownSuggestion()639 public void testAllowAllRotations_allowsUpsideDownSuggestion() 640 throws Exception { 641 mBuilder.build(); 642 mTarget.updateOrientation(SCREEN_ORIENTATION_UNSPECIFIED, true); 643 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 644 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 645 .thenReturn(true); 646 freezeRotation(Surface.ROTATION_0); 647 enableOrientationSensor(); 648 649 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 650 assertTrue(waitForUiHandler()); 651 652 verify(mMockStatusBarManagerInternal) 653 .onProposedRotationChanged(Surface.ROTATION_180, true); 654 } 655 656 @Test testDoNotAllowAllRotations_doesNotAllowUpsideDownSuggestion()657 public void testDoNotAllowAllRotations_doesNotAllowUpsideDownSuggestion() 658 throws Exception { 659 mBuilder.build(); 660 mTarget.updateOrientation(SCREEN_ORIENTATION_UNSPECIFIED, true); 661 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 662 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 663 .thenReturn(false); 664 freezeRotation(Surface.ROTATION_0); 665 enableOrientationSensor(); 666 667 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 668 assertTrue(waitForUiHandler()); 669 670 verify(mMockStatusBarManagerInternal) 671 .onProposedRotationChanged(Surface.ROTATION_180, false); 672 } 673 674 @Test testAllowAllRotations_allowAllRotationsBecomesDisabled_forbidsUpsideDownSuggestion()675 public void testAllowAllRotations_allowAllRotationsBecomesDisabled_forbidsUpsideDownSuggestion() 676 throws Exception { 677 mBuilder.build(); 678 mTarget.updateOrientation(SCREEN_ORIENTATION_UNSPECIFIED, true); 679 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 680 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 681 .thenReturn(true); 682 freezeRotation(Surface.ROTATION_0); 683 enableOrientationSensor(); 684 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0)); 685 assertTrue(waitForUiHandler()); 686 687 // Change resource to disallow all rotations. 688 // Reset "allowAllRotations". 689 mTarget.applyCurrentRotation(Surface.ROTATION_0); 690 clearInvocations(mMockStatusBarManagerInternal); 691 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 692 .thenReturn(false); 693 mTarget.resetAllowAllRotations(); 694 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 695 assertTrue(waitForUiHandler()); 696 697 verify(mMockStatusBarManagerInternal) 698 .onProposedRotationChanged(Surface.ROTATION_180, false); 699 } 700 701 @Test testReturnsCompatibleRotation_SensorEnabled_RotationThawed()702 public void testReturnsCompatibleRotation_SensorEnabled_RotationThawed() throws Exception { 703 mBuilder.build(); 704 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 705 706 thawRotation(); 707 708 enableOrientationSensor(); 709 710 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 711 712 final int rotation = mTarget.rotationForOrientation(SCREEN_ORIENTATION_LANDSCAPE, 713 Surface.ROTATION_0); 714 assertTrue("Rotation should be sideways but it's " 715 + Surface.rotationToString(rotation), 716 rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270); 717 } 718 719 @Test testReturnsUserRotation_SensorEnabled_RotationLocked()720 public void testReturnsUserRotation_SensorEnabled_RotationLocked() throws Exception { 721 mBuilder.build(); 722 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 723 724 freezeRotation(Surface.ROTATION_270); 725 726 enableOrientationSensor(); 727 728 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 729 730 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 731 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 732 } 733 734 @Test testReturnsSensorRotation_180degrees_allRotationsAllowed()735 public void testReturnsSensorRotation_180degrees_allRotationsAllowed() 736 throws Exception { 737 mBuilder.build(); 738 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 739 .thenReturn(true); 740 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 741 enableOrientationSensor(); 742 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 743 744 assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( 745 SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); 746 } 747 748 @Test testReturnLastRotation_sensor180_allRotationsNotAllowed()749 public void testReturnLastRotation_sensor180_allRotationsNotAllowed() 750 throws Exception { 751 mBuilder.build(); 752 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 753 .thenReturn(false); 754 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 755 enableOrientationSensor(); 756 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 757 758 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 759 SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); 760 } 761 762 @Test testAllowRotationsIsCached()763 public void testAllowRotationsIsCached() 764 throws Exception { 765 mBuilder.build(); 766 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 767 enableOrientationSensor(); 768 769 // Rotate once to read the resource 770 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 771 .thenReturn(true); 772 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 773 mTarget.rotationForOrientation(SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0); 774 775 // Change resource to disallow all rotations. 776 // Rotate again and 180 degrees rotation should still be returned even if "disallowed". 777 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 778 .thenReturn(false); 779 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 780 assertEquals(Surface.ROTATION_180, mTarget.rotationForOrientation( 781 SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); 782 } 783 784 @Test testResetAllowRotations()785 public void testResetAllowRotations() 786 throws Exception { 787 mBuilder.build(); 788 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 789 enableOrientationSensor(); 790 791 // Rotate once to read the resource 792 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 793 .thenReturn(true); 794 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 795 mTarget.rotationForOrientation(SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0); 796 797 // Change resource to disallow all rotations. 798 // Reset "allowAllRotations". 799 // Rotate again and 180 degrees rotation should not be allowed anymore. 800 when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations)) 801 .thenReturn(false); 802 mTarget.resetAllowAllRotations(); 803 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180)); 804 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 805 SCREEN_ORIENTATION_SENSOR, Surface.ROTATION_0)); 806 } 807 808 @Test testProposedRotationListener()809 public void testProposedRotationListener() throws Exception { 810 mBuilder.build(); 811 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 812 enableOrientationSensor(); 813 814 final int[] receivedRotation = new int[1]; 815 final IBinder listenerBinder = mock(IBinder.class); 816 final IRotationWatcher listener = new IRotationWatcher() { 817 @Override 818 public IBinder asBinder() { 819 return listenerBinder; 820 } 821 822 @Override 823 public void onRotationChanged(int rotation) { 824 receivedRotation[0] = rotation; 825 } 826 }; 827 final RotationWatcherController controller = new RotationWatcherController(sMockWm) { 828 final WindowContainer<?> mContainer = mock(WindowContainer.class); 829 830 @Override 831 WindowContainer<?> getAssociatedWindowContainer(IBinder token) { 832 return mContainer; 833 } 834 }; 835 mTarget.mProposedRotationCallback = 836 rotation -> controller.dispatchProposedRotation(null /* display */, rotation); 837 controller.registerProposedRotationListener(listener, mock(IBinder.class)); 838 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 839 assertEquals(Surface.ROTATION_90, receivedRotation[0]); 840 841 controller.removeRotationWatcher(listener); 842 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0)); 843 assertEquals(Surface.ROTATION_90, receivedRotation[0]); 844 } 845 846 // ==================================================== 847 // Tests for half-fold auto-rotate override of rotation 848 // ==================================================== 849 @Test testUpdatesRotationWhenSensorUpdates_RotationLocked_HalfFolded()850 public void testUpdatesRotationWhenSensorUpdates_RotationLocked_HalfFolded() throws Exception { 851 mBuilder.setSupportHalfFoldAutoRotateOverride(true); 852 mBuilder.build(); 853 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 854 855 enableOrientationSensor(); 856 857 mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN); 858 freezeRotation(Surface.ROTATION_270); 859 860 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0)); 861 assertTrue(waitForUiHandler()); 862 // No rotation... 863 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 864 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 865 866 // ... until half-fold 867 mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED); 868 assertTrue(waitForUiHandler()); 869 verify(sMockWm).updateRotation(false, false); 870 assertTrue(waitForUiHandler()); 871 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 872 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 873 874 // ... then transition back to flat 875 mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN); 876 assertTrue(waitForUiHandler()); 877 verify(sMockWm, atLeast(1)).updateRotation(false, false); 878 assertTrue(waitForUiHandler()); 879 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 880 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 881 } 882 883 @Test sensorRotation_locked_halfFolded_configOff_rotationUnchanged()884 public void sensorRotation_locked_halfFolded_configOff_rotationUnchanged() throws Exception { 885 mBuilder.setIsFoldable(true); 886 mBuilder.setSupportHalfFoldAutoRotateOverride(false); 887 mBuilder.build(); 888 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 889 890 enableOrientationSensor(); 891 892 mTarget.foldStateChanged(DeviceStateController.DeviceState.OPEN); 893 freezeRotation(Surface.ROTATION_270); 894 895 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0)); 896 assertTrue(waitForUiHandler()); 897 // No rotation... 898 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 899 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 900 901 // ... half-fold -> still no rotation 902 mTarget.foldStateChanged(DeviceStateController.DeviceState.HALF_FOLDED); 903 assertTrue(waitForUiHandler()); 904 verify(sMockWm).updateRotation(false, false); 905 assertTrue(waitForUiHandler()); 906 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 907 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 908 } 909 910 // ================================= 911 // Tests for Policy based Rotation 912 // ================================= 913 @Test testReturnsUserRotation_ForceDefaultRotation_Car()914 public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception { 915 mBuilder.build(); 916 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false); 917 918 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT, 919 Surface.ROTATION_180)); 920 } 921 922 @Test testReturnsUserRotation_ForceDefaultRotation_Tv()923 public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception { 924 mBuilder.build(); 925 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true); 926 927 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT, 928 Surface.ROTATION_180)); 929 } 930 931 @Test testReturnsLidOpenRotation_LidOpen()932 public void testReturnsLidOpenRotation_LidOpen() throws Exception { 933 mBuilder.setLidOpenRotation(Surface.ROTATION_90).build(); 934 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 935 936 when(mMockDisplayPolicy.getLidState()).thenReturn( 937 WindowManagerPolicy.WindowManagerFuncs.LID_OPEN); 938 939 freezeRotation(Surface.ROTATION_270); 940 941 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 942 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 943 } 944 945 @Test testReturnsCarDockRotation_CarDockedMode()946 public void testReturnsCarDockRotation_CarDockedMode() throws Exception { 947 mBuilder.setCarDockRotation(Surface.ROTATION_270).build(); 948 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 949 950 when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_CAR); 951 952 freezeRotation(Surface.ROTATION_90); 953 954 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 955 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90)); 956 } 957 958 @Test testReturnsDeskDockRotation_DeskDockedMode()959 public void testReturnsDeskDockRotation_DeskDockedMode() throws Exception { 960 mBuilder.setDeskDockRotation(Surface.ROTATION_270).build(); 961 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 962 963 when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK); 964 965 freezeRotation(Surface.ROTATION_90); 966 967 assertEquals(Surface.ROTATION_270, mTarget.rotationForOrientation( 968 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_90)); 969 } 970 971 @Test testIgnoresDeskDockRotation_whenNoSensorAndLockedRespected()972 public void testIgnoresDeskDockRotation_whenNoSensorAndLockedRespected() throws Exception { 973 mBuilder.setDeskDockRotation(Surface.ROTATION_270).build(); 974 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 975 976 when(mMockDisplayPolicy.getDockMode()).thenReturn(Intent.EXTRA_DOCK_STATE_DESK); 977 978 freezeRotation(Surface.ROTATION_90); 979 980 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 981 SCREEN_ORIENTATION_LOCKED, Surface.ROTATION_90)); 982 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 983 SCREEN_ORIENTATION_NOSENSOR, Surface.ROTATION_90)); 984 } 985 986 @Test testReturnsUserRotation_FixedToUserRotation_IgnoreIncompatibleAppRequest()987 public void testReturnsUserRotation_FixedToUserRotation_IgnoreIncompatibleAppRequest() 988 throws Exception { 989 mBuilder.build(); 990 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 991 992 mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); 993 994 freezeRotation(Surface.ROTATION_180); 995 996 final int rotation = mTarget.rotationForOrientation( 997 ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE, Surface.ROTATION_90); 998 assertEquals(Surface.ROTATION_180, rotation); 999 } 1000 1001 @Test testReturnsUserRotation_NonDefaultDisplay()1002 public void testReturnsUserRotation_NonDefaultDisplay() throws Exception { 1003 mBuilder.setIsDefaultDisplay(false).build(); 1004 configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false); 1005 1006 freezeRotation(Surface.ROTATION_90); 1007 1008 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 1009 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1010 } 1011 1012 @Test testShouldRotateSeamlessly()1013 public void testShouldRotateSeamlessly() throws Exception { 1014 mBuilder.build(); 1015 1016 final WindowState win = mock(WindowState.class); 1017 win.mToken = win.mActivityRecord = mock(ActivityRecord.class); 1018 final WindowManager.LayoutParams attrs = new WindowManager.LayoutParams(); 1019 attrs.rotationAnimation = WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; 1020 1021 doReturn(attrs).when(win).getAttrs(); 1022 doReturn(true).when(mMockDisplayPolicy).navigationBarCanMove(); 1023 doReturn(win).when(mMockDisplayPolicy).getTopFullscreenOpaqueWindow(); 1024 mMockDisplayContent.mCurrentFocus = win; 1025 // This should not affect the condition of shouldRotateSeamlessly. 1026 mTarget.mUpsideDownRotation = Surface.ROTATION_90; 1027 1028 doReturn(true).when(win.mActivityRecord).matchParentBounds(); 1029 // The focused fullscreen opaque window without override bounds should be able to be 1030 // rotated seamlessly. 1031 assertTrue(mTarget.shouldRotateSeamlessly( 1032 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */)); 1033 // Reject any 180 degree because non-movable navbar will be placed in a different position. 1034 doReturn(false).when(mMockDisplayPolicy).navigationBarCanMove(); 1035 assertFalse(mTarget.shouldRotateSeamlessly( 1036 Surface.ROTATION_90, Surface.ROTATION_180, false /* forceUpdate */)); 1037 1038 doReturn(true).when(mMockDisplayPolicy).navigationBarCanMove(); 1039 doReturn(false).when(win.mActivityRecord).matchParentBounds(); 1040 // No seamless rotation if the window may be positioned with offset after rotation. 1041 assertFalse(mTarget.shouldRotateSeamlessly( 1042 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */)); 1043 } 1044 1045 @Test testSensorRotationAfterDisplayChangeBeforeTimeout_ignoresSensor()1046 public void testSensorRotationAfterDisplayChangeBeforeTimeout_ignoresSensor() throws Exception { 1047 mBuilder.setIsFoldable(true) 1048 .setPauseRotationWhenUnfolding(true) 1049 .setDisplaySwitchRotationBlockTimeMs(1000) 1050 .build(); 1051 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 1052 thawRotation(); 1053 enableOrientationSensor(); 1054 1055 mTarget.physicalDisplayChanged(); 1056 1057 moveTimeForward(900); 1058 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 1059 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 1060 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1061 } 1062 1063 @Test testSensorRotationAfterDisplayChangeAfterTimeout_usesSensor()1064 public void testSensorRotationAfterDisplayChangeAfterTimeout_usesSensor() throws Exception { 1065 mBuilder.setIsFoldable(true) 1066 .setPauseRotationWhenUnfolding(true) 1067 .setDisplaySwitchRotationBlockTimeMs(1000) 1068 .build(); 1069 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 1070 thawRotation(); 1071 enableOrientationSensor(); 1072 1073 mTarget.physicalDisplayChanged(); 1074 1075 moveTimeForward(1100); 1076 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 1077 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 1078 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1079 } 1080 1081 @Test testSensorRotationAfterHingeEventBeforeTimeout_ignoresSensor()1082 public void testSensorRotationAfterHingeEventBeforeTimeout_ignoresSensor() throws Exception { 1083 mBuilder.setIsFoldable(true) 1084 .setPauseRotationWhenUnfolding(true) 1085 .setMaxHingeAngle(165) 1086 .setHingeAngleRotationBlockTimeMs(400) 1087 .build(); 1088 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 1089 thawRotation(); 1090 enableOrientationSensor(); 1091 1092 sendHingeAngleEvent(130); 1093 1094 moveTimeForward( 300); 1095 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 1096 assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation( 1097 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1098 } 1099 1100 @Test testSensorRotationAfterHingeEventBeforeTimeoutFlagDisabled_usesSensorData()1101 public void testSensorRotationAfterHingeEventBeforeTimeoutFlagDisabled_usesSensorData() 1102 throws Exception { 1103 mBuilder.setIsFoldable(true) 1104 .setPauseRotationWhenUnfolding(false) 1105 .setMaxHingeAngle(165) 1106 .setHingeAngleRotationBlockTimeMs(400) 1107 .build(); 1108 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 1109 thawRotation(); 1110 enableOrientationSensor(); 1111 1112 sendHingeAngleEvent(130); 1113 1114 moveTimeForward( 300); 1115 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 1116 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 1117 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1118 } 1119 1120 @Test testSensorRotationAfterHingeEventAfterTimeout_usesSensorData()1121 public void testSensorRotationAfterHingeEventAfterTimeout_usesSensorData() throws Exception { 1122 mBuilder.setIsFoldable(true) 1123 .setPauseRotationWhenUnfolding(true) 1124 .setMaxHingeAngle(165) 1125 .setHingeAngleRotationBlockTimeMs(400) 1126 .build(); 1127 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 1128 thawRotation(); 1129 enableOrientationSensor(); 1130 1131 sendHingeAngleEvent(180); 1132 1133 moveTimeForward(1010); 1134 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 1135 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 1136 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1137 } 1138 1139 1140 @Test testSensorRotationAfterLargeHingeEventBeforeTimeout_usesSensor()1141 public void testSensorRotationAfterLargeHingeEventBeforeTimeout_usesSensor() throws Exception { 1142 mBuilder.setIsFoldable(true) 1143 .setPauseRotationWhenUnfolding(true) 1144 .setMaxHingeAngle(165) 1145 .setHingeAngleRotationBlockTimeMs(400) 1146 .build(); 1147 configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false); 1148 thawRotation(); 1149 enableOrientationSensor(); 1150 1151 sendHingeAngleEvent(180); 1152 1153 moveTimeForward(300); 1154 mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_90)); 1155 assertEquals(Surface.ROTATION_90, mTarget.rotationForOrientation( 1156 SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0)); 1157 } 1158 1159 // ======================== 1160 // Non-rotation API Tests 1161 // ======================== 1162 @Test testIsNotFixedToUserRotationByDefault()1163 public void testIsNotFixedToUserRotationByDefault() throws Exception { 1164 mBuilder.build(); 1165 1166 assertFalse("Display rotation should respect app requested orientation by" 1167 + " default.", mTarget.isFixedToUserRotation()); 1168 } 1169 1170 @Test testIsFixedToUserRotation()1171 public void testIsFixedToUserRotation() throws Exception { 1172 mBuilder.build(); 1173 mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED); 1174 1175 assertTrue("Display rotation shouldn't respect app requested orientation if" 1176 + " fixed to user rotation.", mTarget.isFixedToUserRotation()); 1177 } 1178 1179 @Test testIsFixedToUserRotation_displayContentOrientationFixed()1180 public void testIsFixedToUserRotation_displayContentOrientationFixed() throws Exception { 1181 mBuilder.build(); 1182 when(mMockDisplayContent.isDisplayOrientationFixed()).thenReturn(true); 1183 1184 assertFalse("Display rotation should respect app requested orientation if" 1185 + " the display has fixed orientation.", mTarget.isFixedToUserRotation()); 1186 } 1187 moveTimeForward(long timeMillis)1188 private void moveTimeForward(long timeMillis) { 1189 sCurrentUptimeMillis += timeMillis; 1190 sClock.fastForward(timeMillis); 1191 sHandler.timeAdvance(); 1192 } 1193 1194 /** 1195 * Call {@link DisplayRotation#configure(int, int)} to configure {@link #mTarget} 1196 * according to given parameters. 1197 */ configureDisplayRotation(int displayOrientation, boolean isCar, boolean isTv)1198 private void configureDisplayRotation(int displayOrientation, boolean isCar, boolean isTv) { 1199 final int width; 1200 final int height; 1201 switch (displayOrientation) { 1202 case SCREEN_ORIENTATION_LANDSCAPE: 1203 width = 1920; 1204 height = 1080; 1205 break; 1206 case SCREEN_ORIENTATION_PORTRAIT: 1207 width = 1080; 1208 height = 1920; 1209 break; 1210 default: 1211 throw new IllegalArgumentException("displayOrientation needs to be either landscape" 1212 + " or portrait, but we got " 1213 + ActivityInfo.screenOrientationToString(displayOrientation)); 1214 } 1215 1216 final PackageManager mockPackageManager = mock(PackageManager.class); 1217 when(mMockContext.getPackageManager()).thenReturn(mockPackageManager); 1218 when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) 1219 .thenReturn(isCar); 1220 when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK)) 1221 .thenReturn(isTv); 1222 1223 mTarget.configure(width, height); 1224 } 1225 sendHingeAngleEvent(int hingeAngle)1226 private void sendHingeAngleEvent(int hingeAngle) { 1227 mHingeAngleSensorListenerCaptor.getAllValues().forEach(sensorEventListener -> { 1228 try { 1229 sensorEventListener.onSensorChanged(createSensorEvent(mFakeHingeAngleSensor, 1230 hingeAngle)); 1231 } catch (Exception e) { 1232 throw new RuntimeException(e); 1233 } 1234 }); 1235 } 1236 freezeRotation(int rotation)1237 private void freezeRotation(int rotation) { 1238 mTarget.freezeRotation(rotation); 1239 1240 if (mTarget.isDefaultDisplay) { 1241 mAccelerometerRotationObserver.onChange(false); 1242 mUserRotationObserver.onChange(false); 1243 } 1244 } 1245 thawRotation()1246 private void thawRotation() { 1247 mTarget.thawRotation(); 1248 1249 if (mTarget.isDefaultDisplay) { 1250 mAccelerometerRotationObserver.onChange(false); 1251 mUserRotationObserver.onChange(false); 1252 } 1253 } 1254 1255 private class DisplayRotationBuilder { 1256 private boolean mIsDefaultDisplay = true; 1257 private boolean mSupportAutoRotation = true; 1258 private boolean mPauseRotationWhenUnfolding = false; 1259 private boolean mSupportHalfFoldAutoRotateOverride = false; 1260 private int mDisplaySwitchRotationBlockTimeMs; 1261 private int mHingeAngleRotationBlockTimeMs; 1262 private int mMaxHingeAngle; 1263 1264 private int mLidOpenRotation = WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT; 1265 private int mCarDockRotation; 1266 private int mDeskDockRotation; 1267 private int mUndockedHdmiRotation; 1268 private boolean mIsFoldable; 1269 setIsDefaultDisplay(boolean isDefaultDisplay)1270 private DisplayRotationBuilder setIsDefaultDisplay(boolean isDefaultDisplay) { 1271 mIsDefaultDisplay = isDefaultDisplay; 1272 return this; 1273 } 1274 setPauseRotationWhenUnfolding( boolean pauseRotationWhenUnfolding)1275 public DisplayRotationBuilder setPauseRotationWhenUnfolding( 1276 boolean pauseRotationWhenUnfolding) { 1277 mPauseRotationWhenUnfolding = pauseRotationWhenUnfolding; 1278 return this; 1279 } 1280 setDisplaySwitchRotationBlockTimeMs( int displaySwitchRotationBlockTimeMs)1281 public DisplayRotationBuilder setDisplaySwitchRotationBlockTimeMs( 1282 int displaySwitchRotationBlockTimeMs) { 1283 mDisplaySwitchRotationBlockTimeMs = displaySwitchRotationBlockTimeMs; 1284 return this; 1285 } 1286 setHingeAngleRotationBlockTimeMs( int hingeAngleRotationBlockTimeMs)1287 public DisplayRotationBuilder setHingeAngleRotationBlockTimeMs( 1288 int hingeAngleRotationBlockTimeMs) { 1289 mHingeAngleRotationBlockTimeMs = hingeAngleRotationBlockTimeMs; 1290 return this; 1291 } 1292 setMaxHingeAngle(int maxHingeAngle)1293 public DisplayRotationBuilder setMaxHingeAngle(int maxHingeAngle) { 1294 mMaxHingeAngle = maxHingeAngle; 1295 return this; 1296 } 1297 setSupportAutoRotation(boolean supportAutoRotation)1298 private DisplayRotationBuilder setSupportAutoRotation(boolean supportAutoRotation) { 1299 mSupportAutoRotation = supportAutoRotation; 1300 return this; 1301 } 1302 setLidOpenRotation(int rotation)1303 private DisplayRotationBuilder setLidOpenRotation(int rotation) { 1304 mLidOpenRotation = rotation; 1305 return this; 1306 } 1307 setCarDockRotation(int rotation)1308 private DisplayRotationBuilder setCarDockRotation(int rotation) { 1309 mCarDockRotation = rotation; 1310 return this; 1311 } 1312 setDeskDockRotation(int rotation)1313 private DisplayRotationBuilder setDeskDockRotation(int rotation) { 1314 mDeskDockRotation = rotation; 1315 return this; 1316 } 1317 setUndockedHdmiRotation(int rotation)1318 private DisplayRotationBuilder setUndockedHdmiRotation(int rotation) { 1319 mUndockedHdmiRotation = rotation; 1320 return this; 1321 } 1322 setIsFoldable(boolean value)1323 private DisplayRotationBuilder setIsFoldable(boolean value) { 1324 mIsFoldable = value; 1325 return this; 1326 } 1327 setSupportHalfFoldAutoRotateOverride( boolean supportHalfFoldAutoRotateOverride)1328 private DisplayRotationBuilder setSupportHalfFoldAutoRotateOverride( 1329 boolean supportHalfFoldAutoRotateOverride) { 1330 mSupportHalfFoldAutoRotateOverride = supportHalfFoldAutoRotateOverride; 1331 if (supportHalfFoldAutoRotateOverride) { 1332 mIsFoldable = true; 1333 } 1334 return this; 1335 } 1336 captureObservers()1337 private void captureObservers() { 1338 ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass( 1339 ContentObserver.class); 1340 verify(mMockResolver, atMost(1)).registerContentObserver( 1341 eq(Settings.Secure.getUriFor(Settings.Secure.SHOW_ROTATION_SUGGESTIONS)), 1342 anyBoolean(), 1343 captor.capture(), 1344 anyInt()); 1345 if (!captor.getAllValues().isEmpty()) { 1346 mShowRotationSuggestionsObserver = captor.getValue(); 1347 } 1348 1349 captor = ArgumentCaptor.forClass(ContentObserver.class); 1350 verify(mMockResolver, atMost(1)).registerContentObserver( 1351 eq(Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION)), 1352 anyBoolean(), 1353 captor.capture(), 1354 anyInt()); 1355 if (!captor.getAllValues().isEmpty()) { 1356 mAccelerometerRotationObserver = captor.getValue(); 1357 } 1358 1359 captor = ArgumentCaptor.forClass(ContentObserver.class); 1360 verify(mMockResolver, atMost(1)).registerContentObserver( 1361 eq(Settings.System.getUriFor(Settings.System.USER_ROTATION)), 1362 anyBoolean(), 1363 captor.capture(), 1364 anyInt()); 1365 if (!captor.getAllValues().isEmpty()) { 1366 mUserRotationObserver = captor.getValue(); 1367 } 1368 } 1369 createSensor(int type)1370 private Sensor createSensor(int type) throws Exception { 1371 Constructor<Sensor> constr = Sensor.class.getDeclaredConstructor(); 1372 constr.setAccessible(true); 1373 Sensor sensor = constr.newInstance(); 1374 1375 setSensorType(sensor, type); 1376 setSensorField(sensor, "mName", "Mock " + sensor.getStringType() + "/" + type); 1377 setSensorField(sensor, "mVendor", "Mock Vendor"); 1378 setSensorField(sensor, "mVersion", 1); 1379 setSensorField(sensor, "mHandle", -1); 1380 setSensorField(sensor, "mMaxRange", 10); 1381 setSensorField(sensor, "mResolution", 1); 1382 setSensorField(sensor, "mPower", 1); 1383 setSensorField(sensor, "mMinDelay", 1000); 1384 setSensorField(sensor, "mMaxDelay", 1000000000); 1385 setSensorField(sensor, "mFlags", 0); 1386 setSensorField(sensor, "mId", -1); 1387 1388 return sensor; 1389 } 1390 setSensorType(Sensor sensor, int type)1391 private void setSensorType(Sensor sensor, int type) throws Exception { 1392 Method setter = Sensor.class.getDeclaredMethod("setType", Integer.TYPE); 1393 setter.setAccessible(true); 1394 setter.invoke(sensor, type); 1395 } 1396 setSensorField(Sensor sensor, String fieldName, Object value)1397 private void setSensorField(Sensor sensor, String fieldName, Object value) 1398 throws Exception { 1399 Field field = Sensor.class.getDeclaredField(fieldName); 1400 field.setAccessible(true); 1401 field.set(sensor, value); 1402 } 1403 convertRotationToDegrees(@urface.Rotation int rotation)1404 private int convertRotationToDegrees(@Surface.Rotation int rotation) { 1405 switch (rotation) { 1406 case Surface.ROTATION_0: 1407 return 0; 1408 case Surface.ROTATION_90: 1409 return 90; 1410 case Surface.ROTATION_180: 1411 return 180; 1412 case Surface.ROTATION_270: 1413 return 270; 1414 default: 1415 return -1; 1416 } 1417 } 1418 build()1419 private void build() throws Exception { 1420 mMockContext = mock(Context.class); 1421 1422 mMockDisplayContent = mock(DisplayContent.class); 1423 mMockDisplayContent.isDefaultDisplay = mIsDefaultDisplay; 1424 when(mMockDisplayContent.calculateDisplayCutoutForRotation(anyInt())) 1425 .thenReturn(NO_CUTOUT); 1426 when(mMockDisplayContent.getDefaultTaskDisplayArea()) 1427 .thenReturn(mock(TaskDisplayArea.class)); 1428 when(mMockDisplayContent.getWindowConfiguration()) 1429 .thenReturn(new WindowConfiguration()); 1430 1431 Field field = DisplayContent.class 1432 .getDeclaredField("mFixedRotationTransitionListener"); 1433 field.setAccessible(true); 1434 field.set(mMockDisplayContent, mock(FixedRotationTransitionListener.class)); 1435 1436 mMockDisplayPolicy = mock(DisplayPolicy.class); 1437 1438 mMockRes = mock(Resources.class); 1439 when(mMockContext.getResources()).thenReturn((mMockRes)); 1440 when(mMockRes.getBoolean(com.android.internal.R.bool 1441 .config_windowManagerPauseRotationWhenUnfolding)) 1442 .thenReturn(mPauseRotationWhenUnfolding); 1443 when(mMockRes.getInteger(com.android.internal.R.integer 1444 .config_pauseRotationWhenUnfolding_displaySwitchTimeout)) 1445 .thenReturn(mDisplaySwitchRotationBlockTimeMs); 1446 when(mMockRes.getInteger(com.android.internal.R.integer 1447 .config_pauseRotationWhenUnfolding_hingeEventTimeout)) 1448 .thenReturn(mHingeAngleRotationBlockTimeMs); 1449 when(mMockRes.getInteger(com.android.internal.R.integer 1450 .config_pauseRotationWhenUnfolding_maxHingeAngle)) 1451 .thenReturn(mMaxHingeAngle); 1452 when(mMockRes.getBoolean(com.android.internal.R.bool.config_supportAutoRotation)) 1453 .thenReturn(mSupportAutoRotation); 1454 when(mMockRes.getInteger(com.android.internal.R.integer.config_lidOpenRotation)) 1455 .thenReturn(convertRotationToDegrees(mLidOpenRotation)); 1456 when(mMockRes.getInteger(com.android.internal.R.integer.config_carDockRotation)) 1457 .thenReturn(convertRotationToDegrees(mCarDockRotation)); 1458 when(mMockRes.getInteger(com.android.internal.R.integer.config_deskDockRotation)) 1459 .thenReturn(convertRotationToDegrees(mDeskDockRotation)); 1460 when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation)) 1461 .thenReturn(convertRotationToDegrees(mUndockedHdmiRotation)); 1462 1463 mMockSensorManager = mock(SensorManager.class); 1464 when(mMockContext.getSystemService(SensorManager.class)) 1465 .thenReturn(mMockSensorManager); 1466 when(mMockContext.getSystemService(Context.SENSOR_SERVICE)) 1467 .thenReturn(mMockSensorManager); 1468 mFakeOrientationSensor = createSensor(Sensor.TYPE_DEVICE_ORIENTATION); 1469 when(mMockSensorManager.getSensorList(Sensor.TYPE_DEVICE_ORIENTATION)).thenReturn( 1470 Collections.singletonList(mFakeOrientationSensor)); 1471 mFakeHingeAngleSensor = mock(Sensor.class); 1472 when(mMockSensorManager.getDefaultSensor(Sensor.TYPE_HINGE_ANGLE)).thenReturn( 1473 mFakeHingeAngleSensor); 1474 1475 when(mMockContext.getResources().getBoolean( 1476 com.android.internal.R.bool.config_windowManagerHalfFoldAutoRotateOverride)) 1477 .thenReturn(mSupportHalfFoldAutoRotateOverride); 1478 1479 when(mMockContext.getResources().getIntArray( 1480 R.array.config_foldedDeviceStates)) 1481 .thenReturn(mIsFoldable ? new int[]{0} : new int[]{}); 1482 1483 mMockDisplayRotationReversionController = 1484 mock(DisplayRotationReversionController.class); 1485 when(mMockDisplayContent.getRotationReversionController()) 1486 .thenReturn(mMockDisplayRotationReversionController); 1487 1488 mMockResolver = mock(ContentResolver.class); 1489 when(mMockContext.getContentResolver()).thenReturn(mMockResolver); 1490 mFakeSettingsProvider = new FakeSettingsProvider(); 1491 when(mMockResolver.acquireProvider(Settings.AUTHORITY)) 1492 .thenReturn(mFakeSettingsProvider.getIContentProvider()); 1493 1494 mMockDisplayAddress = mock(DisplayAddress.class); 1495 1496 mMockDisplayWindowSettings = mock(DisplayWindowSettings.class); 1497 1498 mMockDeviceStateManager = mock(DeviceStateManager.class); 1499 when(mMockContext.getSystemService(eq(DeviceStateManager.class))) 1500 .thenReturn(mMockDeviceStateManager); 1501 1502 mDeviceStateController = mock(DeviceStateController.class); 1503 mTarget = new TestDisplayRotation(mMockDisplayContent, mMockDisplayAddress, 1504 mMockDisplayPolicy, mMockDisplayWindowSettings, mMockContext, 1505 mDeviceStateController); 1506 1507 reset(sMockWm); 1508 1509 verify(mMockSensorManager, atLeast(0)).registerListener( 1510 mHingeAngleSensorListenerCaptor.capture(), eq(mFakeHingeAngleSensor), anyInt(), 1511 any()); 1512 1513 captureObservers(); 1514 } 1515 } 1516 1517 private class TestDisplayRotation extends DisplayRotation { 1518 IntConsumer mProposedRotationCallback; 1519 TestDisplayRotation(DisplayContent dc, DisplayAddress address, DisplayPolicy policy, DisplayWindowSettings displayWindowSettings, Context context, DeviceStateController deviceStateController)1520 TestDisplayRotation(DisplayContent dc, DisplayAddress address, DisplayPolicy policy, 1521 DisplayWindowSettings displayWindowSettings, Context context, 1522 DeviceStateController deviceStateController) { 1523 super(sMockWm, dc, address, policy, displayWindowSettings, context, new Object(), 1524 deviceStateController, mock(DisplayRotationCoordinator.class)); 1525 } 1526 1527 @Override initImmersiveAppCompatPolicy( WindowManagerService service, DisplayContent displayContent)1528 DisplayRotationImmersiveAppCompatPolicy initImmersiveAppCompatPolicy( 1529 WindowManagerService service, DisplayContent displayContent) { 1530 return mDisplayRotationImmersiveAppCompatPolicyMock; 1531 } 1532 1533 @Override dispatchProposedRotation(int rotation)1534 void dispatchProposedRotation(int rotation) { 1535 if (mProposedRotationCallback != null) { 1536 mProposedRotationCallback.accept(rotation); 1537 } 1538 } 1539 1540 @Override getHandler()1541 Handler getHandler() { 1542 return sHandler; 1543 } 1544 1545 @Override uptimeMillis()1546 long uptimeMillis() { 1547 return sCurrentUptimeMillis; 1548 } 1549 } 1550 } 1551