summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/LaunchParamsUtil.java129
-rw-r--r--services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java98
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;