Loading services/core/java/com/android/server/wm/ActivityRecord.java +2 −3 Original line number Diff line number Diff line Loading @@ -1371,7 +1371,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final Rect spaceToFill = transformedBounds != null ? transformedBounds : inMultiWindowMode() ? task.getBounds() ? getRootTask().getBounds() : getRootTask().getParent().getBounds(); mLetterbox.layout(spaceToFill, w.getFrame(), mTmpPoint); } else if (mLetterbox != null) { Loading Loading @@ -6589,8 +6589,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // which point, the activity type is still undefined if it will be standard. // For other non-standard types, the type is set in the constructor, so this should // not be a problem. && isActivityTypeStandardOrUndefined() && !mAtmService.mForceResizableActivities; && isActivityTypeStandardOrUndefined(); } @Override Loading services/core/java/com/android/server/wm/DisplayContent.java +1 −1 Original line number Diff line number Diff line Loading @@ -3604,7 +3604,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp && mImeLayeringTarget.mActivityRecord.matchParentBounds() // IME is attached to non-Letterboxed app windows, other than windows with // LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER flag. (Refer to WS.isLetterboxedAppWindow()) && mImeLayeringTarget.matchesRootDisplayAreaBounds(); && mImeLayeringTarget.matchesDisplayAreaBounds(); } /** Loading services/core/java/com/android/server/wm/Task.java +58 −32 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.isSplitScreenWindowingMode; import static android.app.WindowConfiguration.windowingModeToString; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; Loading Loading @@ -2859,6 +2860,29 @@ class Task extends WindowContainer<WindowContainer> { adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig); if (windowingMode == WINDOWING_MODE_FREEFORM) { computeFreeformBounds(outOverrideBounds, newParentConfig); return; } if (isSplitScreenWindowingMode(windowingMode) || windowingMode == WINDOWING_MODE_MULTI_WINDOW) { // This is to compute whether the task should be letterboxed to handle non-resizable app // in multi window. There is no split screen only logic. computeLetterboxBounds(outOverrideBounds, newParentConfig); } } /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. */ @VisibleForTesting void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent". outBounds.setEmpty(); computeLetterboxBounds(outBounds, newParentConfig); } /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */ private void computeFreeformBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { // by policy, make sure the window remains within parent somewhere final float density = ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT; Loading @@ -2874,26 +2898,23 @@ class Task extends WindowContainer<WindowContainer> { parentBounds.intersect(stableBounds); } fitWithinBounds(outOverrideBounds, parentBounds, fitWithinBounds(outBounds, parentBounds, (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP), (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP)); // Prevent to overlap caption with stable insets. final int offsetTop = parentBounds.top - outOverrideBounds.top; final int offsetTop = parentBounds.top - outBounds.top; if (offsetTop > 0) { outOverrideBounds.offset(0, offsetTop); } outBounds.offset(0, offsetTop); } } /** * Compute bounds (letterbox or pillarbox) for * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the * orientation change and the requested orientation is different from the parent. * Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation * change and the requested orientation is different from the parent. */ void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent". outBounds.setEmpty(); private void computeLetterboxBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { if (handlesOrientationChangeFromDescendant()) { // No need to letterbox at task level. Display will handle fixed-orientation requests. return; Loading Loading @@ -2951,6 +2972,8 @@ class Task extends WindowContainer<WindowContainer> { aspect = letterboxAspectRatioOverride > MIN_TASK_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; // Store the current bounds to be able to revert to size compat mode values below if needed. mTmpFullBounds.set(outBounds); if (forcedOrientation == ORIENTATION_LANDSCAPE) { final int height = (int) Math.rint(parentWidth / aspect); final int top = parentBounds.centerY() - height / 2; Loading @@ -2969,7 +2992,7 @@ class Task extends WindowContainer<WindowContainer> { // The app shouldn't be resized, we only do task letterboxing if the compat bounds // is also from the same task letterbox. Otherwise, clear the task bounds to show // app in size compat mode. outBounds.setEmpty(); outBounds.set(mTmpFullBounds); } } } Loading Loading @@ -3355,8 +3378,9 @@ class Task extends WindowContainer<WindowContainer> { @Override boolean handlesOrientationChangeFromDescendant() { return super.handlesOrientationChangeFromDescendant() // Display won't rotate for the orientation request if the TaskDisplayArea can't // specify orientation. // Display won't rotate for the orientation request if the Task/TaskDisplayArea // can't specify orientation. && canSpecifyOrientation() && getDisplayArea().canSpecifyOrientation(); } Loading Loading @@ -3869,7 +3893,9 @@ class Task extends WindowContainer<WindowContainer> { } boolean isTaskLetterboxed() { return getWindowingMode() == WINDOWING_MODE_FULLSCREEN && !matchParentBounds(); // No letterbox for multi window root task return !matchParentBounds() && (getWindowingMode() == WINDOWING_MODE_FULLSCREEN || !isRootTask()); } @Override Loading services/core/java/com/android/server/wm/WindowState.java +12 −8 Original line number Diff line number Diff line Loading @@ -2110,12 +2110,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getDisplayContent().getBounds().equals(getBounds()); } boolean matchesRootDisplayAreaBounds() { RootDisplayArea root = getRootDisplayArea(); if (root == null || root == getDisplayContent()) { boolean matchesDisplayAreaBounds() { final DisplayArea displayArea = getDisplayArea(); if (displayArea == null) { return matchesDisplayBounds(); } return root.getBounds().equals(getBounds()); return displayArea.getBounds().equals(getBounds()); } /** Loading Loading @@ -3762,16 +3762,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getDisplayContent().mCurrentFocus == this; } /** Is this window in a container that takes up the entire screen space? */ private boolean inAppWindowThatMatchesParentBounds() { return mActivityRecord == null || (mActivityRecord.matchParentBounds() && !inMultiWindowMode()); } /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or * is transitioning into/out-of fullscreen. */ /** @return true when the window should be letterboxed. */ boolean isLetterboxedAppWindow() { return !inMultiWindowMode() && !matchesRootDisplayAreaBounds() // Fullscreen mode but doesn't fill display area. return (!inMultiWindowMode() && !matchesDisplayAreaBounds()) // Activity in size compat. || (mActivityRecord != null && mActivityRecord.inSizeCompatMode()) // Task letterboxed. || (getTask() != null && getTask().isTaskLetterboxed()) // Letterboxed for display cutout. || isLetterboxedForDisplayCutout(); } Loading services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -558,7 +558,7 @@ public class DisplayContentTests extends WindowTestsBase { // hence isLetterboxedAppWindow() returns true. ws.mActivityRecord.getConfiguration().windowConfiguration.setBounds(new Rect(1, 1, 1, 1)); assertFalse("matchesRootDisplayAreaBounds() should return false", ws.matchesRootDisplayAreaBounds()); ws.matchesDisplayAreaBounds()); assertTrue("isLetterboxedAppWindow() should return true", ws.isLetterboxedAppWindow()); assertTrue("IME shouldn't be attached to app", dc.computeImeParent() != dc.getImeTarget(IME_TARGET_LAYERING).getWindow() Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +2 −3 Original line number Diff line number Diff line Loading @@ -1371,7 +1371,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A final Rect spaceToFill = transformedBounds != null ? transformedBounds : inMultiWindowMode() ? task.getBounds() ? getRootTask().getBounds() : getRootTask().getParent().getBounds(); mLetterbox.layout(spaceToFill, w.getFrame(), mTmpPoint); } else if (mLetterbox != null) { Loading Loading @@ -6589,8 +6589,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // which point, the activity type is still undefined if it will be standard. // For other non-standard types, the type is set in the constructor, so this should // not be a problem. && isActivityTypeStandardOrUndefined() && !mAtmService.mForceResizableActivities; && isActivityTypeStandardOrUndefined(); } @Override Loading
services/core/java/com/android/server/wm/DisplayContent.java +1 −1 Original line number Diff line number Diff line Loading @@ -3604,7 +3604,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp && mImeLayeringTarget.mActivityRecord.matchParentBounds() // IME is attached to non-Letterboxed app windows, other than windows with // LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER flag. (Refer to WS.isLetterboxedAppWindow()) && mImeLayeringTarget.matchesRootDisplayAreaBounds(); && mImeLayeringTarget.matchesDisplayAreaBounds(); } /** Loading
services/core/java/com/android/server/wm/Task.java +58 −32 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.app.WindowConfiguration.activityTypeToString; import static android.app.WindowConfiguration.isSplitScreenWindowingMode; import static android.app.WindowConfiguration.windowingModeToString; import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; Loading Loading @@ -2859,6 +2860,29 @@ class Task extends WindowContainer<WindowContainer> { adjustForMinimalTaskDimensions(outOverrideBounds, previousBounds, newParentConfig); if (windowingMode == WINDOWING_MODE_FREEFORM) { computeFreeformBounds(outOverrideBounds, newParentConfig); return; } if (isSplitScreenWindowingMode(windowingMode) || windowingMode == WINDOWING_MODE_MULTI_WINDOW) { // This is to compute whether the task should be letterboxed to handle non-resizable app // in multi window. There is no split screen only logic. computeLetterboxBounds(outOverrideBounds, newParentConfig); } } /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}. */ @VisibleForTesting void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent". outBounds.setEmpty(); computeLetterboxBounds(outBounds, newParentConfig); } /** Computes bounds for {@link WindowConfiguration#WINDOWING_MODE_FREEFORM}. */ private void computeFreeformBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { // by policy, make sure the window remains within parent somewhere final float density = ((float) newParentConfig.densityDpi) / DisplayMetrics.DENSITY_DEFAULT; Loading @@ -2874,26 +2898,23 @@ class Task extends WindowContainer<WindowContainer> { parentBounds.intersect(stableBounds); } fitWithinBounds(outOverrideBounds, parentBounds, fitWithinBounds(outBounds, parentBounds, (int) (density * WindowState.MINIMUM_VISIBLE_WIDTH_IN_DP), (int) (density * WindowState.MINIMUM_VISIBLE_HEIGHT_IN_DP)); // Prevent to overlap caption with stable insets. final int offsetTop = parentBounds.top - outOverrideBounds.top; final int offsetTop = parentBounds.top - outBounds.top; if (offsetTop > 0) { outOverrideBounds.offset(0, offsetTop); } outBounds.offset(0, offsetTop); } } /** * Compute bounds (letterbox or pillarbox) for * {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN} when the parent doesn't handle the * orientation change and the requested orientation is different from the parent. * Computes bounds (letterbox or pillarbox) when the parent doesn't handle the orientation * change and the requested orientation is different from the parent. */ void computeFullscreenBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { // In FULLSCREEN mode, always start with empty bounds to indicate "fill parent". outBounds.setEmpty(); private void computeLetterboxBounds(@NonNull Rect outBounds, @NonNull Configuration newParentConfig) { if (handlesOrientationChangeFromDescendant()) { // No need to letterbox at task level. Display will handle fixed-orientation requests. return; Loading Loading @@ -2951,6 +2972,8 @@ class Task extends WindowContainer<WindowContainer> { aspect = letterboxAspectRatioOverride > MIN_TASK_LETTERBOX_ASPECT_RATIO ? letterboxAspectRatioOverride : aspect; // Store the current bounds to be able to revert to size compat mode values below if needed. mTmpFullBounds.set(outBounds); if (forcedOrientation == ORIENTATION_LANDSCAPE) { final int height = (int) Math.rint(parentWidth / aspect); final int top = parentBounds.centerY() - height / 2; Loading @@ -2969,7 +2992,7 @@ class Task extends WindowContainer<WindowContainer> { // The app shouldn't be resized, we only do task letterboxing if the compat bounds // is also from the same task letterbox. Otherwise, clear the task bounds to show // app in size compat mode. outBounds.setEmpty(); outBounds.set(mTmpFullBounds); } } } Loading Loading @@ -3355,8 +3378,9 @@ class Task extends WindowContainer<WindowContainer> { @Override boolean handlesOrientationChangeFromDescendant() { return super.handlesOrientationChangeFromDescendant() // Display won't rotate for the orientation request if the TaskDisplayArea can't // specify orientation. // Display won't rotate for the orientation request if the Task/TaskDisplayArea // can't specify orientation. && canSpecifyOrientation() && getDisplayArea().canSpecifyOrientation(); } Loading Loading @@ -3869,7 +3893,9 @@ class Task extends WindowContainer<WindowContainer> { } boolean isTaskLetterboxed() { return getWindowingMode() == WINDOWING_MODE_FULLSCREEN && !matchParentBounds(); // No letterbox for multi window root task return !matchParentBounds() && (getWindowingMode() == WINDOWING_MODE_FULLSCREEN || !isRootTask()); } @Override Loading
services/core/java/com/android/server/wm/WindowState.java +12 −8 Original line number Diff line number Diff line Loading @@ -2110,12 +2110,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getDisplayContent().getBounds().equals(getBounds()); } boolean matchesRootDisplayAreaBounds() { RootDisplayArea root = getRootDisplayArea(); if (root == null || root == getDisplayContent()) { boolean matchesDisplayAreaBounds() { final DisplayArea displayArea = getDisplayArea(); if (displayArea == null) { return matchesDisplayBounds(); } return root.getBounds().equals(getBounds()); return displayArea.getBounds().equals(getBounds()); } /** Loading Loading @@ -3762,16 +3762,20 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP return getDisplayContent().mCurrentFocus == this; } /** Is this window in a container that takes up the entire screen space? */ private boolean inAppWindowThatMatchesParentBounds() { return mActivityRecord == null || (mActivityRecord.matchParentBounds() && !inMultiWindowMode()); } /** @return true when the window is in fullscreen mode, but has non-fullscreen bounds set, or * is transitioning into/out-of fullscreen. */ /** @return true when the window should be letterboxed. */ boolean isLetterboxedAppWindow() { return !inMultiWindowMode() && !matchesRootDisplayAreaBounds() // Fullscreen mode but doesn't fill display area. return (!inMultiWindowMode() && !matchesDisplayAreaBounds()) // Activity in size compat. || (mActivityRecord != null && mActivityRecord.inSizeCompatMode()) // Task letterboxed. || (getTask() != null && getTask().isTaskLetterboxed()) // Letterboxed for display cutout. || isLetterboxedForDisplayCutout(); } Loading
services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +1 −1 Original line number Diff line number Diff line Loading @@ -558,7 +558,7 @@ public class DisplayContentTests extends WindowTestsBase { // hence isLetterboxedAppWindow() returns true. ws.mActivityRecord.getConfiguration().windowConfiguration.setBounds(new Rect(1, 1, 1, 1)); assertFalse("matchesRootDisplayAreaBounds() should return false", ws.matchesRootDisplayAreaBounds()); ws.matchesDisplayAreaBounds()); assertTrue("isLetterboxedAppWindow() should return true", ws.isLetterboxedAppWindow()); assertTrue("IME shouldn't be attached to app", dc.computeImeParent() != dc.getImeTarget(IME_TARGET_LAYERING).getWindow() Loading