| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| * use this file except in compliance with the License. You may obtain a copy of |
| * the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| * License for the specific language governing permissions and limitations under |
| * the License. |
| */ |
| package android.server.cts; |
| |
| import static android.server.cts.ActivityManagerState.STATE_RESUMED; |
| |
| import android.platform.test.annotations.Presubmit; |
| |
| import com.android.ddmlib.Log.LogLevel; |
| import com.android.tradefed.log.LogUtil.CLog; |
| |
| import java.awt.Rectangle; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import static android.server.cts.ActivityAndWindowManagersState.dpToPx; |
| |
| /** |
| * Build: mmma -j32 cts/hostsidetests/services |
| * Run: cts/hostsidetests/services/activityandwindowmanager/util/run-test CtsServicesHostTestCases android.server.cts.ActivityManagerAppConfigurationTests |
| */ |
| public class ActivityManagerAppConfigurationTests extends ActivityManagerTestBase { |
| private static final String RESIZEABLE_ACTIVITY_NAME = "ResizeableActivity"; |
| private static final String TEST_ACTIVITY_NAME = "TestActivity"; |
| private static final String PORTRAIT_ACTIVITY_NAME = "PortraitOrientationActivity"; |
| private static final String LANDSCAPE_ACTIVITY_NAME = "LandscapeOrientationActivity"; |
| private static final String NIGHT_MODE_ACTIVITY = "NightModeActivity"; |
| private static final String DIALOG_WHEN_LARGE_ACTIVITY = "DialogWhenLargeActivity"; |
| |
| private static final String TRANSLUCENT_ACTIVITY = "TranslucentLandscapeActivity"; |
| |
| private static final String TRANSLUCENT_CURRENT_PACKAGE = "android.server.translucentapp"; |
| |
| private static final String EXTRA_LAUNCH_NEW_TASK = "launch_new_task"; |
| |
| private static final int SMALL_WIDTH_DP = 426; |
| private static final int SMALL_HEIGHT_DP = 320; |
| |
| /** |
| * Tests that the WindowManager#getDefaultDisplay() and the Configuration of the Activity |
| * has an updated size when the Activity is resized from fullscreen to docked state. |
| * |
| * The Activity handles configuration changes, so it will not be restarted between resizes. |
| * On Configuration changes, the Activity logs the Display size and Configuration width |
| * and heights. The values reported in fullscreen should be larger than those reported in |
| * docked state. |
| */ |
| public void testConfigurationUpdatesWhenResizedFromFullscreen() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| String logSeparator = clearLogcat(); |
| launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID); |
| final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| logSeparator = clearLogcat(); |
| moveActivityToStack(RESIZEABLE_ACTIVITY_NAME, DOCKED_STACK_ID); |
| final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| assertSizesAreSane(fullscreenSizes, dockedSizes); |
| } |
| |
| /** |
| * Same as {@link #testConfigurationUpdatesWhenResizedFromFullscreen()} but resizing |
| * from docked state to fullscreen (reverse). |
| */ |
| // TODO: Flaky, add to presubmit when b/63404575 is fixed. |
| public void testConfigurationUpdatesWhenResizedFromDockedStack() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| String logSeparator = clearLogcat(); |
| launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, DOCKED_STACK_ID); |
| final ReportedSizes dockedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| logSeparator = clearLogcat(); |
| moveActivityToStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID); |
| final ReportedSizes fullscreenSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| assertSizesAreSane(fullscreenSizes, dockedSizes); |
| } |
| |
| /** |
| * Tests whether the Display sizes change when rotating the device. |
| */ |
| public void testConfigurationUpdatesWhenRotatingWhileFullscreen() throws Exception { |
| if (!supportsRotation()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no rotation support"); |
| return; |
| } |
| setDeviceRotation(0); |
| final String logSeparator = clearLogcat(); |
| launchActivityInStack(RESIZEABLE_ACTIVITY_NAME, FULLSCREEN_WORKSPACE_STACK_ID); |
| final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| rotateAndCheckSizes(initialSizes); |
| } |
| |
| /** |
| * Same as {@link #testConfigurationUpdatesWhenRotatingWhileFullscreen()} but when the Activity |
| * is in the docked stack. |
| */ |
| // TODO: Flaky, add to presubmit when b/63404575 is fixed. |
| public void testConfigurationUpdatesWhenRotatingWhileDocked() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| setDeviceRotation(0); |
| final String logSeparator = clearLogcat(); |
| launchActivityInDockStack(LAUNCHING_ACTIVITY); |
| // Launch our own activity to side in case Recents (or other activity to side) doesn't |
| // support rotation. |
| getLaunchActivityBuilder().setToSide(true).setTargetActivityName(TEST_ACTIVITY_NAME) |
| .execute(); |
| // Launch target activity in docked stack. |
| getLaunchActivityBuilder().setTargetActivityName(RESIZEABLE_ACTIVITY_NAME).execute(); |
| final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| rotateAndCheckSizes(initialSizes); |
| } |
| |
| /** |
| * Same as {@link #testConfigurationUpdatesWhenRotatingWhileDocked()} but when the Activity |
| * is launched to side from docked stack. |
| */ |
| public void testConfigurationUpdatesWhenRotatingToSideFromDocked() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| setDeviceRotation(0); |
| |
| final String logSeparator = clearLogcat(); |
| launchActivityInDockStack(LAUNCHING_ACTIVITY); |
| |
| getLaunchActivityBuilder().setToSide(true).setTargetActivityName(RESIZEABLE_ACTIVITY_NAME) |
| .execute(); |
| final ReportedSizes initialSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| |
| rotateAndCheckSizes(initialSizes); |
| } |
| |
| private void rotateAndCheckSizes(ReportedSizes prevSizes) throws Exception { |
| for (int rotation = 3; rotation >= 0; --rotation) { |
| final String logSeparator = clearLogcat(); |
| final int actualStackId = mAmWmState.getAmState().getTaskByActivityName( |
| RESIZEABLE_ACTIVITY_NAME).mStackId; |
| final int displayId = mAmWmState.getAmState().getStackById(actualStackId).mDisplayId; |
| setDeviceRotation(rotation); |
| final int newDeviceRotation = getDeviceRotation(displayId); |
| if (newDeviceRotation == INVALID_DEVICE_ROTATION) { |
| CLog.logAndDisplay(LogLevel.WARN, "Got an invalid device rotation value. " |
| + "Continuing the test despite of that, but it is likely to fail."); |
| } else if (rotation != newDeviceRotation) { |
| CLog.logAndDisplay(LogLevel.INFO, "This device doesn't support locked user " |
| + "rotation mode. Not continuing the rotation checks."); |
| return; |
| } |
| |
| final ReportedSizes rotatedSizes = getActivityDisplaySize(RESIZEABLE_ACTIVITY_NAME, |
| logSeparator); |
| assertSizesRotate(prevSizes, rotatedSizes); |
| prevSizes = rotatedSizes; |
| } |
| } |
| |
| /** |
| * Tests when activity moved from fullscreen stack to docked and back. Activity will be |
| * relaunched twice and it should have same config as initial one. |
| */ |
| public void testSameConfigurationFullSplitFullRelaunch() throws Exception { |
| moveActivityFullSplitFull(TEST_ACTIVITY_NAME); |
| } |
| |
| /** |
| * Same as {@link #testSameConfigurationFullSplitFullRelaunch} but without relaunch. |
| */ |
| @Presubmit |
| public void testSameConfigurationFullSplitFullNoRelaunch() throws Exception { |
| moveActivityFullSplitFull(RESIZEABLE_ACTIVITY_NAME); |
| } |
| |
| /** |
| * Launches activity in fullscreen stack, moves to docked stack and back to fullscreen stack. |
| * Last operation is done in a way which simulates split-screen divider movement maximizing |
| * docked stack size and then moving task to fullscreen stack - the same way it is done when |
| * user long-presses overview/recents button to exit split-screen. |
| * Asserts that initial and final reported sizes in fullscreen stack are the same. |
| */ |
| private void moveActivityFullSplitFull(String activityName) throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| // Launch to fullscreen stack and record size. |
| String logSeparator = clearLogcat(); |
| launchActivityInStack(activityName, FULLSCREEN_WORKSPACE_STACK_ID); |
| final ReportedSizes initialFullscreenSizes = getActivityDisplaySize(activityName, |
| logSeparator); |
| final Rectangle displayRect = getDisplayRect(activityName); |
| |
| // Move to docked stack. |
| logSeparator = clearLogcat(); |
| moveActivityToStack(activityName, DOCKED_STACK_ID); |
| final ReportedSizes dockedSizes = getActivityDisplaySize(activityName, logSeparator); |
| assertSizesAreSane(initialFullscreenSizes, dockedSizes); |
| // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack |
| // will come up. |
| launchActivityInStack(activityName, DOCKED_STACK_ID); |
| mAmWmState.computeState(mDevice, new String[] { activityName }, |
| false /* compareTaskAndStackBounds */); |
| |
| // Resize docked stack to fullscreen size. This will trigger activity relaunch with |
| // non-empty override configuration corresponding to fullscreen size. |
| logSeparator = clearLogcat(); |
| runCommandAndPrintOutput("am stack resize " + DOCKED_STACK_ID + " 0 0 " |
| + displayRect.width + " " + displayRect.height); |
| // Move activity back to fullscreen stack. |
| moveActivityToStack(activityName, FULLSCREEN_WORKSPACE_STACK_ID); |
| final ReportedSizes finalFullscreenSizes = getActivityDisplaySize(activityName, |
| logSeparator); |
| |
| // After activity configuration was changed twice it must report same size as original one. |
| assertSizesAreSame(initialFullscreenSizes, finalFullscreenSizes); |
| } |
| |
| /** |
| * Tests when activity moved from docked stack to fullscreen and back. Activity will be |
| * relaunched twice and it should have same config as initial one. |
| */ |
| public void testSameConfigurationSplitFullSplitRelaunch() throws Exception { |
| moveActivitySplitFullSplit(TEST_ACTIVITY_NAME); |
| } |
| |
| /** |
| * Same as {@link #testSameConfigurationSplitFullSplitRelaunch} but without relaunch. |
| */ |
| public void testSameConfigurationSplitFullSplitNoRelaunch() throws Exception { |
| moveActivitySplitFullSplit(RESIZEABLE_ACTIVITY_NAME); |
| } |
| |
| /** |
| * Tests that an activity with the DialogWhenLarge theme can transform properly when in split |
| * screen. |
| */ |
| @Presubmit |
| public void testDialogWhenLargeSplitSmall() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| launchActivityInStack(DIALOG_WHEN_LARGE_ACTIVITY, DOCKED_STACK_ID); |
| final ActivityManagerState.ActivityStack stack = mAmWmState.getAmState() |
| .getStackById(DOCKED_STACK_ID); |
| final WindowManagerState.Display display = |
| mAmWmState.getWmState().getDisplay(stack.mDisplayId); |
| final int density = display.getDpi(); |
| final int smallWidthPx = dpToPx(SMALL_WIDTH_DP, density); |
| final int smallHeightPx = dpToPx(SMALL_HEIGHT_DP, density); |
| |
| runCommandAndPrintOutput("am stack resize " + DOCKED_STACK_ID + " 0 0 " |
| + smallWidthPx + " " + smallHeightPx); |
| mAmWmState.waitForValidState(mDevice, DIALOG_WHEN_LARGE_ACTIVITY, DOCKED_STACK_ID); |
| } |
| |
| /** |
| * Test that device handles consequent requested orientations and displays the activities. |
| */ |
| @Presubmit |
| public void testFullscreenAppOrientationRequests() throws Exception { |
| String logSeparator = clearLogcat(); |
| launchActivity(PORTRAIT_ACTIVITY_NAME); |
| mAmWmState.assertVisibility(PORTRAIT_ACTIVITY_NAME, true /* visible */); |
| ReportedSizes reportedSizes = |
| getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator); |
| assertEquals("portrait activity should be in portrait", |
| 1 /* portrait */, reportedSizes.orientation); |
| logSeparator = clearLogcat(); |
| |
| launchActivity(LANDSCAPE_ACTIVITY_NAME); |
| mAmWmState.assertVisibility(LANDSCAPE_ACTIVITY_NAME, true /* visible */); |
| reportedSizes = |
| getLastReportedSizesForActivity(LANDSCAPE_ACTIVITY_NAME, logSeparator); |
| assertEquals("landscape activity should be in landscape", |
| 2 /* landscape */, reportedSizes.orientation); |
| logSeparator = clearLogcat(); |
| |
| launchActivity(PORTRAIT_ACTIVITY_NAME); |
| mAmWmState.assertVisibility(PORTRAIT_ACTIVITY_NAME, true /* visible */); |
| reportedSizes = |
| getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator); |
| assertEquals("portrait activity should be in portrait", |
| 1 /* portrait */, reportedSizes.orientation); |
| logSeparator = clearLogcat(); |
| } |
| |
| public void testNonfullscreenAppOrientationRequests() throws Exception { |
| String logSeparator = clearLogcat(); |
| launchActivity(PORTRAIT_ACTIVITY_NAME); |
| final ReportedSizes initialReportedSizes = |
| getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator); |
| assertEquals("portrait activity should be in portrait", |
| 1 /* portrait */, initialReportedSizes.orientation); |
| logSeparator = clearLogcat(); |
| |
| // TODO(b/38225467): Target SDK 26 specific package when SDK 27 released. |
| launchActivityInComponent(TRANSLUCENT_CURRENT_PACKAGE, TRANSLUCENT_ACTIVITY); |
| assertEquals("Legacy non-fullscreen activity requested landscape orientation", |
| 0 /* landscape */, mAmWmState.getWmState().getLastOrientation()); |
| |
| // TODO(b/36897968): uncomment once we can suppress unsupported configurations |
| // final ReportedSizes updatedReportedSizes = |
| // getLastReportedSizesForActivity(PORTRAIT_ACTIVITY_NAME, logSeparator); |
| // assertEquals("portrait activity should not have moved from portrait", |
| // 1 /* portrait */, updatedReportedSizes.orientation); |
| } |
| |
| // TODO(b/38225467): Uncomment when SDK 27 is released. |
| // public void testNonFullscreenActivityProhibited() throws Exception { |
| // setComponentName(TRANSLUCENT_CURRENT_PACKAGE); |
| // launchActivity(TRANSLUCENT_ACTIVITY); |
| // mAmWmState.assertNotResumedActivity( |
| // "target SDK > 25 non-fullscreen activity should not reach onResume", |
| // TRANSLUCENT_ACTIVITY); |
| // } |
| |
| // TODO(b/38225467): rename to testLegacyNonFullscreenActivityPermitted |
| public void testNonFullscreenActivityPermitted() throws Exception { |
| // TODO(b/38225467): Target SDK 26 specific package when SDK 27 released. |
| setComponentName(TRANSLUCENT_CURRENT_PACKAGE); |
| setDeviceRotation(0); |
| |
| launchActivity(TRANSLUCENT_ACTIVITY); |
| mAmWmState.assertResumedActivity( |
| "target SDK <= 26 non-fullscreen activity should be allowed to launch", |
| TRANSLUCENT_ACTIVITY); |
| assertEquals("non-fullscreen activity requested landscape orientation", |
| 0 /* landscape */, mAmWmState.getWmState().getLastOrientation()); |
| } |
| |
| /** |
| * Test that device handles moving between two tasks with different orientations. |
| */ |
| public void testTaskCloseRestoreOrientation() throws Exception { |
| // Start landscape activity. |
| launchActivity(LANDSCAPE_ACTIVITY_NAME); |
| mAmWmState.assertVisibility(LANDSCAPE_ACTIVITY_NAME, true /* visible */); |
| assertEquals("Fullscreen app requested landscape orientation", |
| 0 /* landscape */, mAmWmState.getWmState().getLastOrientation()); |
| |
| // Start another activity in a different task. |
| launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY); |
| |
| // Request portrait |
| executeShellCommand(getOrientationBroadcast(1 /*portrait*/)); |
| mAmWmState.waitForRotation(mDevice, 1); |
| |
| // Finish activity |
| executeShellCommand(FINISH_ACTIVITY_BROADCAST); |
| |
| // Verify that activity brought to front is in originally requested orientation. |
| mAmWmState.waitForValidState(mDevice, LANDSCAPE_ACTIVITY_NAME); |
| assertEquals("Should return to app in landscape orientation", |
| 0 /* landscape */, mAmWmState.getWmState().getLastOrientation()); |
| } |
| |
| /** |
| * Test that device handles moving between two tasks with different orientations. |
| */ |
| public void testTaskMoveToBackOrientation() throws Exception { |
| // Start landscape activity. |
| launchActivity(LANDSCAPE_ACTIVITY_NAME); |
| mAmWmState.assertVisibility(LANDSCAPE_ACTIVITY_NAME, true /* visible */); |
| assertEquals("Fullscreen app requested landscape orientation", |
| 0 /* landscape */, mAmWmState.getWmState().getLastOrientation()); |
| |
| // Start another activity in a different task. |
| launchActivityInNewTask(BROADCAST_RECEIVER_ACTIVITY); |
| |
| // Request portrait |
| executeShellCommand(getOrientationBroadcast(1 /*portrait*/)); |
| mAmWmState.waitForRotation(mDevice, 1); |
| |
| // Finish activity |
| executeShellCommand(MOVE_TASK_TO_BACK_BROADCAST); |
| |
| // Verify that activity brought to front is in originally requested orientation. |
| mAmWmState.waitForValidState(mDevice, LANDSCAPE_ACTIVITY_NAME); |
| assertEquals("Should return to app in landscape orientation", |
| 0 /* landscape */, mAmWmState.getWmState().getLastOrientation()); |
| } |
| |
| /** |
| * Test that device doesn't change device orientation by app request while in multi-window. |
| */ |
| public void testSplitscreenPortraitAppOrientationRequests() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| requestOrientationInSplitScreen(1 /* portrait */, LANDSCAPE_ACTIVITY_NAME); |
| } |
| |
| /** |
| * Test that device doesn't change device orientation by app request while in multi-window. |
| */ |
| public void testSplitscreenLandscapeAppOrientationRequests() throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| requestOrientationInSplitScreen(0 /* landscape */, PORTRAIT_ACTIVITY_NAME); |
| } |
| |
| /** |
| * Rotate the device and launch specified activity in split-screen, checking if orientation |
| * didn't change. |
| */ |
| private void requestOrientationInSplitScreen(int orientation, String activity) |
| throws Exception { |
| // Set initial orientation. |
| setDeviceRotation(orientation); |
| |
| // Launch activities that request orientations and check that device doesn't rotate. |
| launchActivityInDockStack(LAUNCHING_ACTIVITY); |
| |
| getLaunchActivityBuilder().setToSide(true).setMultipleTask(true) |
| .setTargetActivityName(activity).execute(); |
| mAmWmState.computeState(mDevice, new String[] {activity}); |
| mAmWmState.assertVisibility(activity, true /* visible */); |
| assertEquals("Split-screen apps shouldn't influence device orientation", |
| orientation, mAmWmState.getWmState().getRotation()); |
| |
| getLaunchActivityBuilder().setMultipleTask(true).setTargetActivityName(activity).execute(); |
| mAmWmState.computeState(mDevice, new String[] {activity}); |
| mAmWmState.assertVisibility(activity, true /* visible */); |
| assertEquals("Split-screen apps shouldn't influence device orientation", |
| orientation, mAmWmState.getWmState().getRotation()); |
| } |
| |
| /** |
| * Launches activity in docked stack, moves to fullscreen stack and back to docked stack. |
| * Asserts that initial and final reported sizes in docked stack are the same. |
| */ |
| private void moveActivitySplitFullSplit(String activityName) throws Exception { |
| if (!supportsSplitScreenMultiWindow()) { |
| CLog.logAndDisplay(LogLevel.INFO, "Skipping test: no multi-window support"); |
| return; |
| } |
| |
| // Launch to docked stack and record size. |
| String logSeparator = clearLogcat(); |
| launchActivityInStack(activityName, DOCKED_STACK_ID); |
| final ReportedSizes initialDockedSizes = getActivityDisplaySize(activityName, logSeparator); |
| // Make sure docked stack is focused. This way when we dismiss it later fullscreen stack |
| // will come up. |
| launchActivityInStack(activityName, DOCKED_STACK_ID); |
| mAmWmState.computeState(mDevice, new String[] { activityName }, |
| false /* compareTaskAndStackBounds */); |
| |
| // Move to fullscreen stack. |
| logSeparator = clearLogcat(); |
| moveActivityToStack(activityName, FULLSCREEN_WORKSPACE_STACK_ID); |
| final ReportedSizes fullscreenSizes = getActivityDisplaySize(activityName, logSeparator); |
| assertSizesAreSane(fullscreenSizes, initialDockedSizes); |
| |
| // Move activity back to docked stack. |
| logSeparator = clearLogcat(); |
| moveActivityToStack(activityName, DOCKED_STACK_ID); |
| final ReportedSizes finalDockedSizes = getActivityDisplaySize(activityName, logSeparator); |
| |
| // After activity configuration was changed twice it must report same size as original one. |
| assertSizesAreSame(initialDockedSizes, finalDockedSizes); |
| } |
| |
| /** |
| * Asserts that after rotation, the aspect ratios of display size, metrics, and configuration |
| * have flipped. |
| */ |
| private static void assertSizesRotate(ReportedSizes rotationA, ReportedSizes rotationB) |
| throws Exception { |
| assertEquals(rotationA.displayWidth, rotationA.metricsWidth); |
| assertEquals(rotationA.displayHeight, rotationA.metricsHeight); |
| assertEquals(rotationB.displayWidth, rotationB.metricsWidth); |
| assertEquals(rotationB.displayHeight, rotationB.metricsHeight); |
| |
| final boolean beforePortrait = rotationA.displayWidth < rotationA.displayHeight; |
| final boolean afterPortrait = rotationB.displayWidth < rotationB.displayHeight; |
| assertFalse(beforePortrait == afterPortrait); |
| |
| final boolean beforeConfigPortrait = rotationA.widthDp < rotationA.heightDp; |
| final boolean afterConfigPortrait = rotationB.widthDp < rotationB.heightDp; |
| assertEquals(beforePortrait, beforeConfigPortrait); |
| assertEquals(afterPortrait, afterConfigPortrait); |
| |
| assertEquals(rotationA.smallestWidthDp, rotationB.smallestWidthDp); |
| } |
| |
| /** |
| * Throws an AssertionError if fullscreenSizes has widths/heights (depending on aspect ratio) |
| * that are smaller than the dockedSizes. |
| */ |
| private static void assertSizesAreSane(ReportedSizes fullscreenSizes, ReportedSizes dockedSizes) |
| throws Exception { |
| final boolean portrait = fullscreenSizes.displayWidth < fullscreenSizes.displayHeight; |
| if (portrait) { |
| assertTrue(dockedSizes.displayHeight < fullscreenSizes.displayHeight); |
| assertTrue(dockedSizes.heightDp < fullscreenSizes.heightDp); |
| assertTrue(dockedSizes.metricsHeight < fullscreenSizes.metricsHeight); |
| } else { |
| assertTrue(dockedSizes.displayWidth < fullscreenSizes.displayWidth); |
| assertTrue(dockedSizes.widthDp < fullscreenSizes.widthDp); |
| assertTrue(dockedSizes.metricsWidth < fullscreenSizes.metricsWidth); |
| } |
| } |
| |
| /** |
| * Throws an AssertionError if sizes are different. |
| */ |
| private static void assertSizesAreSame(ReportedSizes firstSize, ReportedSizes secondSize) |
| throws Exception { |
| assertEquals(firstSize.widthDp, secondSize.widthDp); |
| assertEquals(firstSize.heightDp, secondSize.heightDp); |
| assertEquals(firstSize.displayWidth, secondSize.displayWidth); |
| assertEquals(firstSize.displayHeight, secondSize.displayHeight); |
| assertEquals(firstSize.metricsWidth, secondSize.metricsWidth); |
| assertEquals(firstSize.metricsHeight, secondSize.metricsHeight); |
| assertEquals(firstSize.smallestWidthDp, secondSize.smallestWidthDp); |
| } |
| |
| private ReportedSizes getActivityDisplaySize(String activityName, String logSeparator) |
| throws Exception { |
| mAmWmState.computeState(mDevice, new String[] { activityName }, |
| false /* compareTaskAndStackBounds */); |
| final ReportedSizes details = getLastReportedSizesForActivity(activityName, logSeparator); |
| assertNotNull(details); |
| return details; |
| } |
| |
| private Rectangle getDisplayRect(String activityName) |
| throws Exception { |
| final String windowName = getWindowName(activityName); |
| |
| mAmWmState.computeState(mDevice, new String[] {activityName}); |
| mAmWmState.assertFocusedWindow("Test window must be the front window.", windowName); |
| |
| final List<WindowManagerState.WindowState> tempWindowList = new ArrayList<>(); |
| mAmWmState.getWmState().getMatchingVisibleWindowState(windowName, tempWindowList); |
| |
| assertEquals("Should have exactly one window state for the activity.", 1, |
| tempWindowList.size()); |
| |
| WindowManagerState.WindowState windowState = tempWindowList.get(0); |
| assertNotNull("Should have a valid window", windowState); |
| |
| WindowManagerState.Display display = mAmWmState.getWmState() |
| .getDisplay(windowState.getDisplayId()); |
| assertNotNull("Should be on a display", display); |
| |
| return display.getDisplayRect(); |
| } |
| |
| /** |
| * Test launching an activity which requests specific UI mode during creation. |
| */ |
| public void testLaunchWithUiModeChange() throws Exception { |
| // Launch activity that changes UI mode and handles this configuration change. |
| launchActivity(NIGHT_MODE_ACTIVITY); |
| mAmWmState.waitForActivityState(mDevice, NIGHT_MODE_ACTIVITY, STATE_RESUMED); |
| |
| // Check if activity is launched successfully. |
| mAmWmState.assertVisibility(NIGHT_MODE_ACTIVITY, true /* visible */); |
| mAmWmState.assertFocusedActivity("Launched activity should be focused", |
| NIGHT_MODE_ACTIVITY); |
| mAmWmState.assertResumedActivity("Launched activity must be resumed", NIGHT_MODE_ACTIVITY); |
| } |
| } |