From b3968b811823658b8f0a272b26ca2adb883d94ae Mon Sep 17 00:00:00 2001 From: Kazuki Takise Date: Tue, 8 Feb 2022 16:51:52 +0900 Subject: [PATCH] Calculate freeform bounds for fullscreen task Currently several pieces of logic in LaunchParamsModifier assume that bounds doesn't need to be calculated for fullscreen tasks, but this is incorrect in that the bounds calculated in LaunchParamsModifier can be used as last non-fullscreen bounds for fullscreen tasks. Last non-fullscreen bounds is useful in an environment such as ARC++ where the windowing mode of a task changes between freeform and fullscreen. With this CL, freeform bounds calculation (ActivityOption, layout, getTaskBounds) is applied to fullscreen tasks too. This CL also involves some refactoring around getting bounds from ActivityOption and WindowLayout (especially for fullscreen tasks and tasks whose windowing mode is MULTI_WINDOW). Bug: 185427982 Test: atest WmTests:TaskLaunchParamsModifierTests Change-Id: I3ccaf1ebfa7bcc11c371b0043fbfa11366f7a8f3 --- .../server/wm/TaskLaunchParamsModifier.java | 63 +++++++++++-------- .../wm/TaskLaunchParamsModifierTests.java | 25 ++++++++ 2 files changed, 62 insertions(+), 26 deletions(-) diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 4edda74df3285..aa51ac375efe7 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -181,26 +181,34 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is // different, we should recalculating the bounds. boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow = false; - final boolean canApplyFreeformPolicy = + // Note that initial bounds needs to be set to fullscreen tasks too as it's used as restore + // bounds. + final boolean canCalculateBoundsForFullscreenTask = + canCalculateBoundsForFullscreenTask(suggestedDisplayArea, launchMode); + final boolean canApplyFreeformWindowPolicy = canApplyFreeformWindowPolicy(suggestedDisplayArea, launchMode); - if (mSupervisor.canUseActivityOptionsLaunchBounds(options) - && (canApplyFreeformPolicy || canApplyPipWindowPolicy(launchMode))) { + final boolean canApplyWindowLayout = layout != null + && (canApplyFreeformWindowPolicy || canCalculateBoundsForFullscreenTask); + final boolean canApplyBoundsFromActivityOptions = + mSupervisor.canUseActivityOptionsLaunchBounds(options) + && (canApplyFreeformWindowPolicy + || canApplyPipWindowPolicy(launchMode) + || canCalculateBoundsForFullscreenTask); + + if (canApplyBoundsFromActivityOptions) { hasInitialBounds = true; - launchMode = launchMode == WINDOWING_MODE_UNDEFINED + // |launchMode| at this point can be fullscreen, PIP, MultiWindow, etc. Only set + // freeform windowing mode if appropriate by checking |canApplyFreeformWindowPolicy|. + launchMode = launchMode == WINDOWING_MODE_UNDEFINED && canApplyFreeformWindowPolicy ? WINDOWING_MODE_FREEFORM : launchMode; outParams.mBounds.set(options.getLaunchBounds()); if (DEBUG) appendLog("activity-options-bounds=" + outParams.mBounds); - } else if (launchMode == WINDOWING_MODE_PINNED) { - // System controls PIP window's bounds, so don't apply launch bounds. - if (DEBUG) appendLog("empty-window-layout-for-pip"); - } else if (launchMode == WINDOWING_MODE_FULLSCREEN) { - if (DEBUG) appendLog("activity-options-fullscreen=" + outParams.mBounds); - } else if (layout != null && canApplyFreeformPolicy) { + } else if (canApplyWindowLayout) { mTmpBounds.set(currentParams.mBounds); getLayoutBounds(suggestedDisplayArea, root, layout, mTmpBounds); if (!mTmpBounds.isEmpty()) { - launchMode = WINDOWING_MODE_FREEFORM; + launchMode = canApplyFreeformWindowPolicy ? WINDOWING_MODE_FREEFORM : launchMode; outParams.mBounds.set(mTmpBounds); hasInitialBounds = true; hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow = true; @@ -210,6 +218,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } } else if (launchMode == WINDOWING_MODE_MULTI_WINDOW && options != null && options.getLaunchBounds() != null) { + // TODO: Investigate whether we can migrate this clause to the + // |canApplyBoundsFromActivityOptions| case above. outParams.mBounds.set(options.getLaunchBounds()); hasInitialBounds = true; if (DEBUG) appendLog("multiwindow-activity-options-bounds=" + outParams.mBounds); @@ -249,11 +259,9 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { if (!currentParams.mBounds.isEmpty()) { // Carry over bounds from callers regardless of launch mode because bounds is still // used to restore last non-fullscreen bounds when launch mode is not freeform. - // Therefore it's not a resolution step for non-freeform launch mode and only - // consider it fully resolved only when launch mode is freeform. outParams.mBounds.set(currentParams.mBounds); + fullyResolvedCurrentParam = true; if (launchMode == WINDOWING_MODE_FREEFORM) { - fullyResolvedCurrentParam = true; if (DEBUG) appendLog("inherit-bounds=" + outParams.mBounds); } } @@ -368,7 +376,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // an existing task. adjustBoundsToAvoidConflictInDisplayArea(taskDisplayArea, outParams.mBounds); } - } else if (taskDisplayArea.inFreeformWindowingMode()) { + } else { if (source != null && source.inFreeformWindowingMode() && resolvedMode == WINDOWING_MODE_FREEFORM && outParams.mBounds.isEmpty() @@ -545,10 +553,19 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { return display.getDisplayId() == source.getDisplayId(); } + private boolean canCalculateBoundsForFullscreenTask(@NonNull TaskDisplayArea displayArea, + int launchMode) { + return mSupervisor.mService.mSupportsFreeformWindowManagement + && ((displayArea.getWindowingMode() == WINDOWING_MODE_FULLSCREEN + && launchMode == WINDOWING_MODE_UNDEFINED) + || launchMode == WINDOWING_MODE_FULLSCREEN); + } + private boolean canApplyFreeformWindowPolicy(@NonNull TaskDisplayArea suggestedDisplayArea, int launchMode) { return mSupervisor.mService.mSupportsFreeformWindowManagement - && (suggestedDisplayArea.inFreeformWindowingMode() + && ((suggestedDisplayArea.inFreeformWindowingMode() + && launchMode == WINDOWING_MODE_UNDEFINED) || launchMode == WINDOWING_MODE_FREEFORM); } @@ -710,16 +727,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { private void getTaskBounds(@NonNull ActivityRecord root, @NonNull TaskDisplayArea displayArea, @NonNull ActivityInfo.WindowLayout layout, int resolvedMode, boolean hasInitialBounds, @NonNull Rect inOutBounds) { - if (resolvedMode == WINDOWING_MODE_FULLSCREEN) { - // We don't handle letterboxing here. Letterboxing will be handled by valid checks - // later. - inOutBounds.setEmpty(); - if (DEBUG) appendLog("maximized-bounds"); - return; - } - - if (resolvedMode != WINDOWING_MODE_FREEFORM) { - // We don't apply freeform bounds adjustment to other windowing modes. + if (resolvedMode != WINDOWING_MODE_FREEFORM + && resolvedMode != WINDOWING_MODE_FULLSCREEN) { + // This function should be used only for freeform bounds adjustment. Freeform bounds + // needs to be set to fullscreen tasks too as restore bounds. if (DEBUG) { appendLog("skip-bounds-" + WindowConfiguration.windowingModeToString(resolvedMode)); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index a6c5fd87c8d85..dce9f66356535 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -570,6 +570,29 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { WINDOWING_MODE_FULLSCREEN); } + @Test + public void testBoundsInOptionsInfersFullscreenWithBoundsOnFreeformSupportFullscreenDisplay() { + final TestDisplayContent fullscreenDisplay = createNewDisplayContent( + WINDOWING_MODE_FULLSCREEN); + mAtm.mTaskSupervisor.mService.mSupportsFreeformWindowManagement = true; + + final ActivityOptions options = ActivityOptions.makeBasic(); + final Rect expectedBounds = new Rect(0, 0, 100, 100); + options.setLaunchBounds(expectedBounds); + + mCurrent.mPreferredTaskDisplayArea = fullscreenDisplay.getDefaultTaskDisplayArea(); + + assertEquals(RESULT_CONTINUE, + new CalculateRequestBuilder().setOptions(options).calculate()); + + // Setting bounds shouldn't lead to freeform windowing mode on fullscreen display by + // default (even with freeform support), but we need to check here if the bounds is set even + // with fullscreen windowing mode in case it's restored later. + assertEquivalentWindowingMode(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode, + WINDOWING_MODE_FULLSCREEN); + assertEquals(expectedBounds, mResult.mBounds); + } + @Test public void testInheritsFreeformModeFromSourceOnFullscreenDisplay() { final TestDisplayContent fullscreenDisplay = createNewDisplayContent( @@ -952,6 +975,8 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { WINDOWING_MODE_FULLSCREEN); final ActivityRecord source = createSourceActivity(fullscreenDisplay); source.getTask().setWindowingMode(WINDOWING_MODE_FREEFORM); + // Set some bounds to avoid conflict with the other activity. + source.setBounds(100, 100, 200, 200); final ActivityOptions options = ActivityOptions.makeBasic(); final Rect expected = new Rect(0, 0, 150, 150);