Merge "Make `DesktopModeLaunchParamsModifier` no-op if desktop mode not supported" into main
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1d6b151..a926a70 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -6987,4 +6987,7 @@
 
     <!-- Wear devices: An intent action that is used for remote intent. -->
     <string name="config_wearRemoteIntentAction" translatable="false" />
+
+    <!-- Whether desktop mode is supported on the current device  -->
+    <bool name="config_isDesktopModeSupported">false</bool>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4322b55..06c0188 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -5387,4 +5387,7 @@
   <java-symbol type="bool" name="config_deviceSupportsHighPerfTransitions" />
 
   <java-symbol type="string" name="config_wearRemoteIntentAction" />
+
+  <!-- Whether desktop mode is supported on the current device  -->
+  <java-symbol type="bool" name="config_isDesktopModeSupported" />
 </resources>
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index c68b0be..a541c59 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -148,7 +148,4 @@
 
     <!-- Whether pointer pilfer is required to start back animation. -->
     <bool name="config_backAnimationRequiresPointerPilfer">true</bool>
-
-    <!-- Whether desktop mode is supported on the current device  -->
-    <bool name="config_isDesktopModeSupported">false</bool>
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
index 494d893..32c22c0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java
@@ -20,9 +20,9 @@
 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;
-import com.android.wm.shell.R;
 
 /**
  * Constants for desktop mode feature
diff --git a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
index 925a077..61f5679 100644
--- a/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/DesktopModeLaunchParamsModifier.java
@@ -19,13 +19,17 @@
 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.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.Slog;
 
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.wm.LaunchParamsController.LaunchParamsModifier;
 import com.android.window.flags.Flags;
 /**
@@ -37,14 +41,24 @@
             TAG_WITH_CLASS_NAME ? "DesktopModeLaunchParamsModifier" : TAG_ATM;
     private static final boolean DEBUG = false;
 
-    private static final boolean DESKTOP_MODE_PROTO2_SUPPORTED =
-            SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
     public static final float DESKTOP_MODE_INITIAL_BOUNDS_SCALE =
             SystemProperties
                     .getInt("persist.wm.debug.desktop_mode_initial_bounds_scale", 75) / 100f;
 
+    /**
+     * 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);
+
     private StringBuilder mLogBuilder;
 
+    private final Context mContext;
+
+    DesktopModeLaunchParamsModifier(@NonNull Context context) {
+        mContext = context;
+    }
+
     @Override
     public int onCalculate(@Nullable Task task, @Nullable ActivityInfo.WindowLayout layout,
             @Nullable ActivityRecord activity, @Nullable ActivityRecord source,
@@ -65,7 +79,7 @@
             LaunchParamsController.LaunchParams currentParams,
             LaunchParamsController.LaunchParams outParams) {
 
-        if (!isDesktopModeEnabled()) {
+        if (!canEnterDesktopMode(mContext)) {
             appendLog("desktop mode is not enabled, continuing");
             return RESULT_CONTINUE;
         }
@@ -90,7 +104,7 @@
         // previous windowing mode to be restored even if the desktop mode state has changed.
         // Let task launches inherit the windowing mode from the source task if available, which
         // should have the desired windowing mode set by WM Shell. See b/286929122.
-        if (isDesktopModeEnabled() && source != null && source.getTask() != null) {
+        if (source != null && source.getTask() != null) {
             final Task sourceTask = source.getTask();
             outParams.mWindowingMode = sourceTask.getWindowingMode();
             appendLog("inherit-from-source=" + outParams.mWindowingMode);
@@ -147,4 +161,29 @@
     static boolean isDesktopModeEnabled() {
         return Flags.enableDesktopWindowingMode();
     }
+
+    /**
+     * Return {@code true} if desktop mode should be restricted to supported devices.
+     */
+    @VisibleForTesting
+    public boolean enforceDeviceRestrictions() {
+        return ENFORCE_DEVICE_RESTRICTIONS;
+    }
+
+    /**
+     * Return {@code true} if the current device supports desktop mode.
+     */
+    @VisibleForTesting
+    public 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.
+     */
+    boolean canEnterDesktopMode(@NonNull Context context) {
+        return isDesktopModeEnabled()
+                && (!enforceDeviceRestrictions() || isDesktopModeSupported(context));
+    }
+
 }
diff --git a/services/core/java/com/android/server/wm/LaunchParamsController.java b/services/core/java/com/android/server/wm/LaunchParamsController.java
index 97b5925..d3c3d28 100644
--- a/services/core/java/com/android/server/wm/LaunchParamsController.java
+++ b/services/core/java/com/android/server/wm/LaunchParamsController.java
@@ -64,7 +64,7 @@
     void registerDefaultModifiers(ActivityTaskSupervisor supervisor) {
         // {@link TaskLaunchParamsModifier} handles window layout preferences.
         registerModifier(new TaskLaunchParamsModifier(supervisor));
-        registerModifier(new DesktopModeLaunchParamsModifier());
+        registerModifier(new DesktopModeLaunchParamsModifier(mService.mContext));
     }
 
     /**
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 4060d40..353ba01 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DesktopModeLaunchParamsModifierTests.java
@@ -29,7 +29,10 @@
 import static com.android.server.wm.LaunchParamsController.LaunchParamsModifier.RESULT_SKIP;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 
 import android.graphics.Rect;
 import android.platform.test.annotations.DisableFlags;
@@ -44,6 +47,7 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
 
 /**
  * Tests for desktop mode task bounds.
@@ -58,6 +62,7 @@
 
     private ActivityRecord mActivity;
 
+    @Mock
     private DesktopModeLaunchParamsModifier mTarget;
 
     private LaunchParamsController.LaunchParams mCurrent;
@@ -66,7 +71,8 @@
     @Before
     public void setUp() throws Exception {
         mActivity = new ActivityBuilder(mAtm).build();
-        mTarget = new DesktopModeLaunchParamsModifier();
+        mTarget = spy(new DesktopModeLaunchParamsModifier(mContext));
+        doReturn(true).when(mTarget).isDesktopModeSupported(any());
         mCurrent = new LaunchParamsController.LaunchParams();
         mCurrent.reset();
         mResult = new LaunchParamsController.LaunchParams();
@@ -81,6 +87,21 @@
 
     @Test
     @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    public void testReturnsContinueIfDesktopWindowingIsEnabledOnUnsupportedDevice() {
+        doReturn(false).when(mTarget).isDesktopModeSupported(any());
+        assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setTask(null).calculate());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
+    public void testReturnsDoneIfDesktopWindowingIsEnabledAndUnsupportedDeviceOverridden() {
+        doReturn(false).when(mTarget).enforceDeviceRestrictions();
+        final Task task = new TaskBuilder(mSupervisor).build();
+        assertEquals(RESULT_DONE, new CalculateRequestBuilder().setTask(task).calculate());
+    }
+
+    @Test
+    @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_WINDOWING_MODE)
     public void testReturnsSkipIfTaskIsNull() {
         assertEquals(RESULT_SKIP, new CalculateRequestBuilder().setTask(null).calculate());
     }