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