summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java2
-rw-r--r--services/core/java/com/android/server/wm/AppCompatCameraPolicy.java2
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java99
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeHelper.java66
-rw-r--r--services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java102
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java2
10 files changed, 183 insertions, 102 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 3076b873058d..e7f4422b5958 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -233,7 +233,7 @@ import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_F
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE;
import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE;
import static com.android.server.wm.ActivityTaskManagerService.getInputDispatchingTimeoutMillisLocked;
-import static com.android.server.wm.DesktopModeLaunchParamsModifier.canEnterDesktopMode;
+import static com.android.server.wm.DesktopModeHelper.canEnterDesktopMode;
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
diff --git a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java
index 53729a2a971c..c8955fdd7911 100644
--- a/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatCameraPolicy.java
@@ -47,7 +47,7 @@ class AppCompatCameraPolicy {
final boolean needsDisplayRotationCompatPolicy =
wmService.mLetterboxConfiguration.isCameraCompatTreatmentEnabledAtBuildTime();
final boolean needsCameraCompatFreeformPolicy = Flags.cameraCompatForFreeform()
- && DesktopModeLaunchParamsModifier.canEnterDesktopMode(wmService.mContext);
+ && DesktopModeHelper.canEnterDesktopMode(wmService.mContext);
if (needsDisplayRotationCompatPolicy || needsCameraCompatFreeformPolicy) {
mCameraStateMonitor = new CameraStateMonitor(displayContent, wmService.mH);
mActivityRefresher = new ActivityRefresher(wmService, wmService.mH);
diff --git a/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
new file mode 100644
index 000000000000..f9f5058415c6
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2024 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 com.android.server.wm.LaunchParamsUtil.applyLayoutGravity;
+import static com.android.server.wm.LaunchParamsUtil.calculateLayoutBounds;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.content.pm.ActivityInfo;
+import android.graphics.Rect;
+import android.os.SystemProperties;
+import android.util.Size;
+import android.view.Gravity;
+
+import java.util.function.Consumer;
+
+/**
+ * Calculates the value of the {@link LaunchParamsController.LaunchParams} bounds for the
+ * {@link DesktopModeLaunchParamsModifier}.
+ */
+public final class DesktopModeBoundsCalculator {
+
+ public static final float DESKTOP_MODE_INITIAL_BOUNDS_SCALE = SystemProperties
+ .getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f;
+
+ /**
+ * Updates launch bounds for an activity with respect to its activity options, window layout,
+ * android manifest and task configuration.
+ */
+ static void updateInitialBounds(@NonNull Task task, @Nullable ActivityInfo.WindowLayout layout,
+ @Nullable ActivityRecord activity, @Nullable ActivityOptions options,
+ @NonNull Rect outBounds, @NonNull Consumer<String> logger) {
+ // Use stable frame instead of raw frame to avoid launching freeform windows on top of
+ // stable insets, which usually are system widgets such as sysbar & navbar.
+ final TaskDisplayArea displayArea = task.getDisplayArea();
+ final Rect screenBounds = displayArea.getBounds();
+ final Rect stableBounds = new Rect();
+ displayArea.getStableRect(stableBounds);
+ final int desiredWidth = (int) (stableBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (stableBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+
+ if (options != null && options.getLaunchBounds() != null) {
+ outBounds.set(options.getLaunchBounds());
+ logger.accept("inherit-from-options=" + outBounds);
+ } else if (layout != null) {
+ final int verticalGravity = layout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
+ final int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ if (layout.hasSpecifiedSize()) {
+ calculateLayoutBounds(stableBounds, layout, outBounds,
+ new Size(desiredWidth, desiredHeight));
+ applyLayoutGravity(verticalGravity, horizontalGravity, outBounds,
+ stableBounds);
+ logger.accept("layout specifies sizes, inheriting size and applying gravity");
+ } else if (verticalGravity > 0 || horizontalGravity > 0) {
+ calculateAndCentreInitialBounds(outBounds, screenBounds);
+ applyLayoutGravity(verticalGravity, horizontalGravity, outBounds,
+ stableBounds);
+ logger.accept("layout specifies gravity, applying desired bounds and gravity");
+ }
+ } else {
+ calculateAndCentreInitialBounds(outBounds, screenBounds);
+ logger.accept("layout not specified, applying desired bounds");
+ }
+ }
+
+ /**
+ * Calculates the initial height and width of a task in desktop mode and centers it within the
+ * window bounds.
+ */
+ private static void calculateAndCentreInitialBounds(@NonNull Rect outBounds,
+ @NonNull Rect screenBounds) {
+ // TODO(b/319819547): Account for app constraints so apps do not become letterboxed
+ // The desired dimensions that a fully resizable window should take when initially entering
+ // desktop mode. Calculated as a percentage of the available display area as defined by the
+ // DESKTOP_MODE_INITIAL_BOUNDS_SCALE.
+ final int desiredWidth = (int) (screenBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ final int desiredHeight = (int) (screenBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
+ outBounds.right = desiredWidth;
+ outBounds.bottom = desiredHeight;
+ outBounds.offset(screenBounds.centerX() - outBounds.centerX(),
+ screenBounds.centerY() - outBounds.centerY());
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DesktopModeHelper.java b/services/core/java/com/android/server/wm/DesktopModeHelper.java
new file mode 100644
index 000000000000..1f341147deb1
--- /dev/null
+++ b/services/core/java/com/android/server/wm/DesktopModeHelper.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2024 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 android.annotation.NonNull;
+import android.content.Context;
+import android.os.SystemProperties;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
+
+/**
+ * Constants for desktop mode feature
+ */
+public final class DesktopModeHelper {
+ /**
+ * Flag to indicate whether to restrict desktop mode to supported devices.
+ */
+ private static final boolean ENFORCE_DEVICE_RESTRICTIONS = SystemProperties.getBoolean(
+ "persist.wm.debug.desktop_mode_enforce_device_restrictions", true);
+
+ /** Whether desktop mode is enabled. */
+ static boolean isDesktopModeEnabled() {
+ return Flags.enableDesktopWindowingMode();
+ }
+
+ /**
+ * Return {@code true} if desktop mode should be restricted to supported devices.
+ */
+ @VisibleForTesting
+ static boolean shouldEnforceDeviceRestrictions() {
+ return ENFORCE_DEVICE_RESTRICTIONS;
+ }
+
+ /**
+ * Return {@code true} if the current device supports desktop mode.
+ */
+ // TODO(b/337819319): use a companion object instead.
+ @VisibleForTesting
+ static boolean isDesktopModeSupported(@NonNull Context context) {
+ return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
+ }
+
+ /**
+ * Return {@code true} if desktop mode can be entered on the current device.
+ */
+ static boolean canEnterDesktopMode(@NonNull Context context) {
+ return isDesktopModeEnabled()
+ && (!shouldEnforceDeviceRestrictions() || isDesktopModeSupported(context));
+ }
+}
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 66653caaa73d..aacd3c65154f 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -18,28 +18,21 @@ package com.android.server.wm;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.LaunchParamsUtil.applyLayoutGravity;
-import static com.android.server.wm.LaunchParamsUtil.calculateLayoutBounds;
+import static com.android.server.wm.DesktopModeHelper.canEnterDesktopMode;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityOptions;
import android.content.Context;
import android.content.pm.ActivityInfo;
-import android.graphics.Rect;
import android.os.SystemProperties;
-import android.util.Size;
import android.util.Slog;
-import android.view.Gravity;
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
-import com.android.window.flags.Flags;
/**
* The class that defines default launch params for tasks in desktop mode
*/
-public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
+class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
private static final String TAG =
TAG_WITH_CLASS_NAME ? "DesktopModeLaunchParamsModifier" : TAG_ATM;
@@ -67,8 +60,8 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
@Nullable ActivityRecord activity, @Nullable ActivityRecord source,
@Nullable ActivityOptions options, @Nullable ActivityStarter.Request request, int phase,
- LaunchParamsController.LaunchParams currentParams,
- LaunchParamsController.LaunchParams outParams) {
+ @NonNull LaunchParamsController.LaunchParams currentParams,
+ @NonNull LaunchParamsController.LaunchParams outParams) {
initLogBuilder(task, activity);
int result = calculate(task, layout, activity, source, options, request, phase,
@@ -80,15 +73,15 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
private int calculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
@Nullable ActivityRecord activity, @Nullable ActivityRecord source,
@Nullable ActivityOptions options, @Nullable ActivityStarter.Request request, int phase,
- LaunchParamsController.LaunchParams currentParams,
- LaunchParamsController.LaunchParams outParams) {
+ @NonNull LaunchParamsController.LaunchParams currentParams,
+ @NonNull LaunchParamsController.LaunchParams outParams) {
if (!canEnterDesktopMode(mContext)) {
appendLog("desktop mode is not enabled, skipping");
return RESULT_SKIP;
}
- if (task == null) {
+ if (task == null || !task.isAttached()) {
appendLog("task null, skipping");
return RESULT_SKIP;
}
@@ -123,59 +116,12 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
return RESULT_SKIP;
}
- // Use stable frame instead of raw frame to avoid launching freeform windows on top of
- // stable insets, which usually are system widgets such as sysbar & navbar.
- final Rect stableBounds = new Rect();
- task.getDisplayArea().getStableRect(stableBounds);
- final int desiredWidth = (int) (stableBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- final int desiredHeight = (int) (stableBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
-
- if (options != null && options.getLaunchBounds() != null) {
- outParams.mBounds.set(options.getLaunchBounds());
- appendLog("inherit-from-options=" + outParams.mBounds);
- } else if (layout != null) {
- final int verticalGravity = layout.gravity & Gravity.VERTICAL_GRAVITY_MASK;
- final int horizontalGravity = layout.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
- if (layout.hasSpecifiedSize()) {
- calculateLayoutBounds(stableBounds, layout, outParams.mBounds,
- new Size(desiredWidth, desiredHeight));
- applyLayoutGravity(verticalGravity, horizontalGravity, outParams.mBounds,
- stableBounds);
- appendLog("layout specifies sizes, inheriting size and applying gravity");
- } else if (verticalGravity > 0 || horizontalGravity > 0) {
- calculateAndCentreInitialBounds(task, outParams);
- applyLayoutGravity(verticalGravity, horizontalGravity, outParams.mBounds,
- stableBounds);
- appendLog("layout specifies gravity, applying desired bounds and gravity");
- }
- } else {
- calculateAndCentreInitialBounds(task, outParams);
- appendLog("layout not specified, applying desired bounds");
- }
-
+ DesktopModeBoundsCalculator.updateInitialBounds(task, layout, activity, options,
+ outParams.mBounds, this::appendLog);
appendLog("final desktop mode task bounds set to %s", outParams.mBounds);
return RESULT_CONTINUE;
}
- /**
- * Calculates the initial height and width of a task in desktop mode and centers it within the
- * window bounds.
- */
- private void calculateAndCentreInitialBounds(Task task,
- LaunchParamsController.LaunchParams outParams) {
- // TODO(b/319819547): Account for app constraints so apps do not become letterboxed
- final Rect screenBounds = task.getDisplayArea().getBounds();
- // The desired dimensions that a fully resizable window should take when initially entering
- // desktop mode. Calculated as a percentage of the available display area as defined by the
- // DESKTOP_MODE_INITIAL_BOUNDS_SCALE.
- final int desiredWidth = (int) (screenBounds.width() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- final int desiredHeight = (int) (screenBounds.height() * DESKTOP_MODE_INITIAL_BOUNDS_SCALE);
- outParams.mBounds.right = desiredWidth;
- outParams.mBounds.bottom = desiredHeight;
- outParams.mBounds.offset(screenBounds.centerX() - outParams.mBounds.centerX(),
- screenBounds.centerY() - outParams.mBounds.centerY());
- }
-
private void initLogBuilder(Task task, ActivityRecord activity) {
if (DEBUG) {
mLogBuilder = new StringBuilder(
@@ -190,34 +136,4 @@ public class DesktopModeLaunchParamsModifier implements LaunchParamsModifier {
private void outputLog() {
if (DEBUG) Slog.d(TAG, mLogBuilder.toString());
}
-
- /** Whether desktop mode is enabled. */
- static boolean isDesktopModeEnabled() {
- return Flags.enableDesktopWindowingMode();
- }
-
- /**
- * Return {@code true} if desktop mode should be restricted to supported devices.
- */
- @VisibleForTesting
- static boolean enforceDeviceRestrictions() {
- return ENFORCE_DEVICE_RESTRICTIONS;
- }
-
- /**
- * Return {@code true} if the current device supports desktop mode.
- */
- // TODO(b/337819319): use a companion object instead.
- @VisibleForTesting
- static boolean isDesktopModeSupported(@NonNull Context context) {
- return context.getResources().getBoolean(R.bool.config_isDesktopModeSupported);
- }
-
- /**
- * Return {@code true} if desktop mode can be entered on the current device.
- */
- static boolean canEnterDesktopMode(@NonNull Context context) {
- return isDesktopModeEnabled()
- && (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
- }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java
index 006b37002e23..974a8e8712d8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatCameraPolicyTest.java
@@ -168,7 +168,7 @@ public class AppCompatCameraPolicyTest extends WindowTestsBase {
// TODO(b/350460645): Create Desktop Windowing Robot to reuse common functionalities.
void allowEnterDesktopMode(boolean isAllowed) {
doReturn(isAllowed).when(() ->
- DesktopModeLaunchParamsModifier.canEnterDesktopMode(any()));
+ DesktopModeHelper.canEnterDesktopMode(any()));
}
private AppCompatCameraPolicy getTopAppCompatCameraPolicy() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
index ad3fba3084fe..23a88a1774f4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -430,8 +430,8 @@ public class DesktopModeLaunchParamsModifierTests extends
private void setupDesktopModeLaunchParamsModifier(boolean isDesktopModeSupported,
boolean enforceDeviceRestrictions) {
doReturn(isDesktopModeSupported)
- .when(() -> DesktopModeLaunchParamsModifier.isDesktopModeSupported(any()));
+ .when(() -> DesktopModeHelper.isDesktopModeSupported(any()));
doReturn(enforceDeviceRestrictions)
- .when(DesktopModeLaunchParamsModifier::enforceDeviceRestrictions);
+ .when(DesktopModeHelper::shouldEnforceDeviceRestrictions);
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 65aaf605bdfe..af0856f6109f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -2870,7 +2870,7 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void cameraCompatFreeformFlagEnabled_cameraCompatFreeformPolicyNotNull() {
doReturn(true).when(() ->
- DesktopModeLaunchParamsModifier.canEnterDesktopMode(any()));
+ DesktopModeHelper.canEnterDesktopMode(any()));
assertTrue(createNewDisplay().mAppCompatCameraPolicy.hasCameraCompatFreeformPolicy());
}
@@ -2879,7 +2879,7 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void cameraCompatFreeformFlagNotEnabled_cameraCompatFreeformPolicyIsNull() {
doReturn(true).when(() ->
- DesktopModeLaunchParamsModifier.canEnterDesktopMode(any()));
+ DesktopModeHelper.canEnterDesktopMode(any()));
assertFalse(createNewDisplay().mAppCompatCameraPolicy.hasCameraCompatFreeformPolicy());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index ae88b1baa5b8..afe360430f02 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -1658,7 +1658,7 @@ public class SizeCompatTests extends WindowTestsBase {
@EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
public void testCompatScaling_freeformUnresizeableApp_smallerThanParent_upScaled() {
doReturn(true).when(() ->
- DesktopModeLaunchParamsModifier.canEnterDesktopMode(any()));
+ DesktopModeHelper.canEnterDesktopMode(any()));
final int dw = 600;
final int dh = 800;
final DisplayContent display = new TestDisplayContent.Builder(mAtm, dw, dh)
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 4220f319b8f2..a816aa9b7598 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -202,7 +202,7 @@ public class SystemServicesTestRule implements TestRule {
.mockStatic(DisplayControl.class, mockStubOnly)
.mockStatic(LockGuard.class, mockStubOnly)
.mockStatic(Watchdog.class, mockStubOnly)
- .spyStatic(DesktopModeLaunchParamsModifier.class)
+ .spyStatic(DesktopModeHelper.class)
.strictness(Strictness.LENIENT)
.startMocking();