diff options
| -rw-r--r-- | services/core/java/com/android/server/wm/LaunchParamsUtil.java | 129 | ||||
| -rw-r--r-- | services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java | 98 |
2 files changed, 137 insertions, 90 deletions
diff --git a/services/core/java/com/android/server/wm/LaunchParamsUtil.java b/services/core/java/com/android/server/wm/LaunchParamsUtil.java new file mode 100644 index 000000000000..4122992dd48c --- /dev/null +++ b/services/core/java/com/android/server/wm/LaunchParamsUtil.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2022 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 com.android.server.wm; + +import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; +import static android.util.DisplayMetrics.DENSITY_DEFAULT; + +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; +import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; + +import android.annotation.NonNull; +import android.content.pm.ActivityInfo; +import android.graphics.Rect; +import android.util.Size; + +/** + * The static class that defines some utility constants and functions that are shared among launch + * params modifiers. + */ +class LaunchParamsUtil { + private static final String TAG = TAG_WITH_CLASS_NAME ? "LaunchParamsUtil" : TAG_ATM; + private static final boolean DEBUG = false; + + // Screen size of Nexus 5x + static final int DEFAULT_PORTRAIT_FREEFORM_WIDTH_DP = 412; + static final int DEFAULT_PORTRAIT_FREEFORM_HEIGHT_DP = 732; + + // One of the most common tablet sizes that are small enough to fit in most large screens. + private static final int DEFAULT_LANDSCAPE_FREEFORM_WIDTH_DP = 1064; + private static final int DEFAULT_LANDSCAPE_FREEFORM_HEIGHT_DP = 600; + + private LaunchParamsUtil() {} + + /** + * Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds + * centers at its center or displayArea's app bounds center if inOutBounds is empty. + */ + static void centerBounds(@NonNull TaskDisplayArea displayArea, int width, int height, + @NonNull Rect inOutBounds) { + if (inOutBounds.isEmpty()) { + displayArea.getStableRect(inOutBounds); + } + final int left = inOutBounds.centerX() - width / 2; + final int top = inOutBounds.centerY() - height / 2; + inOutBounds.set(left, top, left + width, top + height); + } + + /** + * Calculate the default size for a freeform environment. |defaultSize| is used as the default + * DP size, but if this is null, the portrait phone size is used. + */ + static Size getDefaultFreeformSize(@NonNull ActivityRecord activityRecord, + @NonNull TaskDisplayArea displayArea, + @NonNull ActivityInfo.WindowLayout layout, int orientation, + @NonNull Rect stableBounds) { + // Get window size based on Nexus 5x screen, we assume that this is enough to show content + // of activities. + final float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT; + final int freeformWidthInDp = (orientation == SCREEN_ORIENTATION_LANDSCAPE) + ? DEFAULT_LANDSCAPE_FREEFORM_WIDTH_DP : DEFAULT_PORTRAIT_FREEFORM_WIDTH_DP; + final int freeformHeightInDp = (orientation == SCREEN_ORIENTATION_LANDSCAPE) + ? DEFAULT_LANDSCAPE_FREEFORM_HEIGHT_DP : DEFAULT_PORTRAIT_FREEFORM_HEIGHT_DP; + final int freeformWidth = (int) (freeformWidthInDp * density + 0.5f); + final int freeformHeight = (int) (freeformHeightInDp * density + 0.5f); + + // Minimum layout requirements. + final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth; + final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight; + + // Max size, which is letterboxing/pillarboxing in displayArea. That's to say the large + // dimension of default size is the small dimension of displayArea size, and the small + // dimension of default size is calculated to keep the same aspect ratio as the + // displayArea's. Here we use stable bounds of displayArea because that indicates the area + // that isn't occupied by system widgets (e.g. sysbar and navbar). + final int portraitHeight = Math.min(stableBounds.width(), stableBounds.height()); + final int otherDimension = Math.max(stableBounds.width(), stableBounds.height()); + final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension; + final int maxWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight + : portraitWidth; + final int maxHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitWidth + : portraitHeight; + final int width = Math.min(maxWidth, Math.max(freeformWidth, layoutMinWidth)); + final int height = Math.min(maxHeight, Math.max(freeformHeight, layoutMinHeight)); + final float aspectRatio = (float) Math.max(width, height) / (float) Math.min(width, height); + + // Aspect ratio requirements. + final float minAspectRatio = activityRecord.getMinAspectRatio(); + final float maxAspectRatio = activityRecord.info.getMaxAspectRatio(); + + // Adjust the width and height to the aspect ratio requirements. + int adjWidth = width; + int adjHeight = height; + if (minAspectRatio >= 1 && aspectRatio < minAspectRatio) { + // The aspect ratio is below the minimum, adjust it to the minimum. + if (orientation == SCREEN_ORIENTATION_LANDSCAPE) { + // Fix the width, scale the height. + adjHeight = (int) (adjWidth / minAspectRatio + 0.5f); + } else { + // Fix the height, scale the width. + adjWidth = (int) (adjHeight / minAspectRatio + 0.5f); + } + } else if (maxAspectRatio >= 1 && aspectRatio > maxAspectRatio) { + // The aspect ratio exceeds the maximum, adjust it to the maximum. + if (orientation == SCREEN_ORIENTATION_LANDSCAPE) { + // Fix the width, scale the height. + adjHeight = (int) (adjWidth / maxAspectRatio + 0.5f); + } else { + // Fix the height, scale the width. + adjWidth = (int) (adjHeight / maxAspectRatio + 0.5f); + } + } + + return new Size(adjWidth, adjHeight); + } +} diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 8e98cb793179..4edda74df328 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -47,6 +47,7 @@ import android.app.WindowConfiguration; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.graphics.Rect; +import android.util.Size; import android.util.Slog; import android.view.Gravity; import android.view.View; @@ -66,10 +67,6 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskLaunchParamsModifier" : TAG_ATM; private static final boolean DEBUG = false; - // Screen size of Nexus 5x - private static final int DEFAULT_PORTRAIT_PHONE_WIDTH_DP = 412; - private static final int DEFAULT_PORTRAIT_PHONE_HEIGHT_DP = 732; - // Allowance of size matching. private static final int EPSILON = 2; @@ -738,7 +735,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } // First we get the default size we want. - getDefaultFreeformSize(root, displayArea, layout, orientation, mTmpBounds); + displayArea.getStableRect(mTmpStableBounds); + final Size defaultSize = LaunchParamsUtil.getDefaultFreeformSize(root, displayArea, + layout, orientation, mTmpStableBounds); + mTmpBounds.set(0, 0, defaultSize.getWidth(), defaultSize.getHeight()); if (hasInitialBounds || sizeMatches(inOutBounds, mTmpBounds)) { // We're here because either input parameters specified initial bounds, or the suggested // bounds have the same size of the default freeform size. We should use the suggested @@ -748,8 +748,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { if (DEBUG) appendLog("freeform-size-orientation-match=" + inOutBounds); } else { // Meh, orientation doesn't match. Let's rotate inOutBounds in-place. - centerBounds(displayArea, inOutBounds.height(), inOutBounds.width(), - inOutBounds); + LaunchParamsUtil.centerBounds(displayArea, inOutBounds.height(), + inOutBounds.width(), inOutBounds); if (DEBUG) appendLog("freeform-orientation-mismatch=" + inOutBounds); } } else { @@ -758,7 +758,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // to the center of suggested bounds (or the displayArea if no suggested bounds). The // default size might be too big to center to source activity bounds in displayArea, so // we may need to move it back to the displayArea. - centerBounds(displayArea, mTmpBounds.width(), mTmpBounds.height(), + LaunchParamsUtil.centerBounds(displayArea, mTmpBounds.width(), mTmpBounds.height(), inOutBounds); adjustBoundsToFitInDisplayArea(displayArea, inOutBounds); if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds); @@ -806,88 +806,6 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { return orientation; } - private void getDefaultFreeformSize(@NonNull ActivityRecord activityRecord, - @NonNull TaskDisplayArea displayArea, - @NonNull ActivityInfo.WindowLayout layout, int orientation, @NonNull Rect bounds) { - // Default size, which is letterboxing/pillarboxing in displayArea. That's to say the large - // dimension of default size is the small dimension of displayArea size, and the small - // dimension of default size is calculated to keep the same aspect ratio as the - // displayArea's. Here we use stable bounds of displayArea because that indicates the area - // that isn't occupied by system widgets (e.g. sysbar and navbar). - final ActivityInfo info = activityRecord.info; - final Rect stableBounds = mTmpStableBounds; - displayArea.getStableRect(stableBounds); - final int portraitHeight = Math.min(stableBounds.width(), stableBounds.height()); - final int otherDimension = Math.max(stableBounds.width(), stableBounds.height()); - final int portraitWidth = (portraitHeight * portraitHeight) / otherDimension; - final int defaultWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitHeight - : portraitWidth; - final int defaultHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? portraitWidth - : portraitHeight; - - // Get window size based on Nexus 5x screen, we assume that this is enough to show content - // of activities. - final float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT; - final int phonePortraitWidth = (int) (DEFAULT_PORTRAIT_PHONE_WIDTH_DP * density + 0.5f); - final int phonePortraitHeight = (int) (DEFAULT_PORTRAIT_PHONE_HEIGHT_DP * density + 0.5f); - final int phoneWidth = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitHeight - : phonePortraitWidth; - final int phoneHeight = (orientation == SCREEN_ORIENTATION_LANDSCAPE) ? phonePortraitWidth - : phonePortraitHeight; - - // Minimum layout requirements. - final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth; - final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight; - - // Aspect ratio requirements. - final float minAspectRatio = activityRecord.getMinAspectRatio(); - final float maxAspectRatio = info.getMaxAspectRatio(); - - final int width = Math.min(defaultWidth, Math.max(phoneWidth, layoutMinWidth)); - final int height = Math.min(defaultHeight, Math.max(phoneHeight, layoutMinHeight)); - final float aspectRatio = (float) Math.max(width, height) / (float) Math.min(width, height); - - // Adjust the width and height to the aspect ratio requirements. - int adjWidth = width; - int adjHeight = height; - if (minAspectRatio >= 1 && aspectRatio < minAspectRatio) { - // The aspect ratio is below the minimum, adjust it to the minimum. - if (orientation == SCREEN_ORIENTATION_LANDSCAPE) { - // Fix the width, scale the height. - adjHeight = (int) (adjWidth / minAspectRatio + 0.5f); - } else { - // Fix the height, scale the width. - adjWidth = (int) (adjHeight / minAspectRatio + 0.5f); - } - } else if (maxAspectRatio >= 1 && aspectRatio > maxAspectRatio) { - // The aspect ratio exceeds the maximum, adjust it to the maximum. - if (orientation == SCREEN_ORIENTATION_LANDSCAPE) { - // Fix the width, scale the height. - adjHeight = (int) (adjWidth / maxAspectRatio + 0.5f); - } else { - // Fix the height, scale the width. - adjWidth = (int) (adjHeight / maxAspectRatio + 0.5f); - } - } - - bounds.set(0, 0, adjWidth, adjHeight); - bounds.offset(stableBounds.left, stableBounds.top); - } - - /** - * Gets centered bounds of width x height. If inOutBounds is not empty, the result bounds - * centers at its center or displayArea's app bounds center if inOutBounds is empty. - */ - private void centerBounds(@NonNull TaskDisplayArea displayArea, int width, int height, - @NonNull Rect inOutBounds) { - if (inOutBounds.isEmpty()) { - displayArea.getStableRect(inOutBounds); - } - final int left = inOutBounds.centerX() - width / 2; - final int top = inOutBounds.centerY() - height / 2; - inOutBounds.set(left, top, left + width, top + height); - } - private void adjustBoundsToFitInDisplayArea(@NonNull TaskDisplayArea displayArea, @NonNull Rect inOutBounds) { final Rect stableBounds = mTmpStableBounds; |