Loading services/core/java/com/android/server/wm/ActivityRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * 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()); } } services/core/java/com/android/server/wm/DesktopModeHelper.java 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * 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)); } } services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java +9 −93 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; } Loading Loading @@ -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( Loading @@ -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)); } } Loading
services/core/java/com/android/server/wm/ActivityRecord.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
services/core/java/com/android/server/wm/AppCompatCameraPolicy.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
services/core/java/com/android/server/wm/DesktopModeBoundsCalculator.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * 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()); } }
services/core/java/com/android/server/wm/DesktopModeHelper.java 0 → 100644 +66 −0 Original line number Diff line number Diff line /* * 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)); } }
services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java +9 −93 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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, Loading @@ -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; } Loading Loading @@ -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( Loading @@ -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)); } }