Add DisplayContent#forceDesktopMode

As WMS#mForceDesktopModeOnExternalDisplays is a flag to force enable
desktop mode on public secondary display.

Since some code points didn't check if the display is public
& secondary display, it may cause some issues like Bubbles using
private virtual display but the content can show system decorations and
IME always failed to show, if user enabled force desktop mode config
from developer option.

Add DC#forceDesktopMode to make sure the check is proper and consistent.

Fix: 163333691
Test: manual as test steps:
1) Enable "Force Desktop Mode on External display" from Settings ->
   Developer option.
2) Launch Message or FB messenger with chat head bubbles
3) Taping EditText and check if soft-keyboard can show up correctly.
Test: atest DisplayContentTests#testForceDesktopMode

Merged-In: I6ec52b6b1642fd547ebc222ae1bf9a2958e5fb2d
Change-Id: I6ec52b6b1642fd547ebc222ae1bf9a2958e5fb2d
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index abfb9c9..553aad1 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -3554,7 +3554,11 @@
             return false;
         }
         return mWmService.mDisplayWindowSettings.shouldShowImeLocked(this)
-                || mWmService.mForceDesktopModeOnExternalDisplays;
+                || forceDesktopMode();
+    }
+
+    boolean forceDesktopMode() {
+        return mWmService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay && !isPrivate();
     }
 
     private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim) {
@@ -4786,7 +4790,7 @@
     boolean supportsSystemDecorations() {
         return (mWmService.mDisplayWindowSettings.shouldShowSystemDecorsLocked(this)
                 || (mDisplay.getFlags() & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0
-                || mWmService.mForceDesktopModeOnExternalDisplays)
+                || forceDesktopMode())
                 // VR virtual display will be used to run and render 2D app within a VR experience.
                 && mDisplayId != mWmService.mVr2dDisplayId
                 // Do not show system decorations on untrusted virtual display.
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 37ecee8..1284e00 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -330,10 +330,8 @@
         // It's also not likely to rotate a TV screen.
         final boolean isTv = mContext.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_LEANBACK);
-        final boolean forceDesktopMode =
-                mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay;
         mDefaultFixedToUserRotation =
-                (isCar || isTv || mService.mIsPc || forceDesktopMode)
+                (isCar || isTv || mService.mIsPc || mDisplayContent.forceDesktopMode())
                 // For debug purposes the next line turns this feature off with:
                 // $ adb shell setprop config.override_forced_orient true
                 // $ adb shell wm size reset
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 470a02e..34b403b 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -248,7 +248,7 @@
         writeSettingsIfNeeded(entry, displayInfo);
     }
 
-    private int getWindowingModeLocked(Entry entry, int displayId) {
+    private int getWindowingModeLocked(Entry entry, DisplayContent dc) {
         int windowingMode = entry != null ? entry.mWindowingMode
                 : WindowConfiguration.WINDOWING_MODE_UNDEFINED;
         // This display used to be in freeform, but we don't support freeform anymore, so fall
@@ -259,10 +259,8 @@
         }
         // No record is present so use default windowing mode policy.
         if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) {
-            final boolean forceDesktopMode = mService.mForceDesktopModeOnExternalDisplays
-                    && displayId != Display.DEFAULT_DISPLAY;
             windowingMode = mService.mAtmService.mSupportsFreeformWindowManagement
-                    && (mService.mIsPc || forceDesktopMode)
+                    && (mService.mIsPc || dc.forceDesktopMode())
                     ? WindowConfiguration.WINDOWING_MODE_FREEFORM
                     : WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
         }
@@ -272,7 +270,7 @@
     int getWindowingModeLocked(DisplayContent dc) {
         final DisplayInfo displayInfo = dc.getDisplayInfo();
         final Entry entry = getEntry(displayInfo);
-        return getWindowingModeLocked(entry, dc.getDisplayId());
+        return getWindowingModeLocked(entry, dc);
     }
 
     void setWindowingModeLocked(DisplayContent dc, int mode) {
@@ -382,7 +380,7 @@
         final Entry entry = getOrCreateEntry(displayInfo);
 
         // Setting windowing mode first, because it may override overscan values later.
-        dc.setWindowingMode(getWindowingModeLocked(entry, dc.getDisplayId()));
+        dc.setWindowingMode(getWindowingModeLocked(entry, dc));
 
         dc.getDisplayRotation().restoreSettings(entry.mUserRotationMode,
                 entry.mUserRotation, entry.mFixedToUserRotation);
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 dc838f1..6a84c13 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -28,6 +28,7 @@
 import static android.os.Build.VERSION_CODES.P;
 import static android.os.Build.VERSION_CODES.Q;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.FLAG_PRIVATE;
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
@@ -95,6 +96,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.DisplayMetrics;
 import android.view.DisplayCutout;
+import android.view.DisplayInfo;
 import android.view.Gravity;
 import android.view.IDisplayWindowRotationCallback;
 import android.view.IDisplayWindowRotationController;
@@ -1439,6 +1441,29 @@
         mDisplayContent.ensureActivitiesVisible(null, 0, false, false);
     }
 
+    @Test
+    public void testForceDesktopMode() {
+        mWm.mForceDesktopModeOnExternalDisplays = true;
+        // Not applicable for default display
+        final DisplayContent defaultDisplay = mWm.mRoot.getDefaultDisplay();
+        assertFalse(defaultDisplay.forceDesktopMode());
+
+        // Not applicable for private secondary display.
+        final DisplayInfo displayInfo = new DisplayInfo();
+        displayInfo.copyFrom(mDisplayInfo);
+        displayInfo.flags = FLAG_PRIVATE;
+        final DisplayContent privateDc = createNewDisplay(displayInfo);
+        assertFalse(privateDc.forceDesktopMode());
+
+        // Applicable for public secondary display.
+        final DisplayContent publicDc = createNewDisplay();
+        assertTrue(publicDc.forceDesktopMode());
+
+        // Make sure forceDesktopMode() is false when the force config is disabled.
+        mWm.mForceDesktopModeOnExternalDisplays = false;
+        assertFalse(publicDc.forceDesktopMode());
+    }
+
     private boolean isOptionsPanelAtRight(int displayId) {
         return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
     }