Implement new API of external display settings (1/2)

- Using DisplaySettings class for storing the display settings.
- Define flags in WindowManager.
- Have direct IWindowManager APIs to set and change display settings at
  runtime.
- Mark TODO to original usage of the flags.
- Add test case of DisplaySettings.
- Expose some APIs for CTS usage.

Bug: 114338689
Test: atest DisplayWindowSettingsTests
Test: atest CtsApacheHttpLegacy27ApiSignatureTestCases
Change-Id: I64ed14866d45cd5817fc3c895b6110c79c37b0ad
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index c51dc52..ab64f61 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -95,12 +95,14 @@
     /**
      * Flag: This display can show its content when non-secure keyguard is shown.
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard
     public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 9;
 
     /**
      * Flag: This display will destroy its content on removal.
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY
     public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10;
 
     /**
@@ -114,6 +116,7 @@
      * status bar, navigation bar, home activity or IME.
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 12;
 
     /**
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index e20793e..b01d67d 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2132,7 +2132,7 @@
         if (density == mInitialDisplayDensity) {
             density = 0;
         }
-        mService.mDisplaySettings.setForcedDensity(this, density, userId);
+        mService.mDisplayWindowSettings.setForcedDensity(this, density, userId);
     }
 
     /** @param mode {@link #FORCE_SCALING_MODE_AUTO} or {@link #FORCE_SCALING_MODE_DISABLED}. */
@@ -2145,7 +2145,7 @@
         Slog.i(TAG_WM, "Using display scaling mode: " + (mDisplayScalingDisabled ? "off" : "auto"));
         mService.reconfigureDisplayLocked(this);
 
-        mService.mDisplaySettings.setForcedScalingMode(this, mode);
+        mService.mDisplayWindowSettings.setForcedScalingMode(this, mode);
     }
 
     /** If the given width and height equal to initial size, the setting will be cleared. */
@@ -2167,7 +2167,7 @@
         if (clear) {
             width = height = 0;
         }
-        mService.mDisplaySettings.setForcedSize(this, width, height);
+        mService.mDisplayWindowSettings.setForcedSize(this, width, height);
     }
 
     void getStableRect(Rect out) {
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 9f98dc5..6ab7090 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -265,7 +265,8 @@
             mUserRotation = userRotation;
             changed = true;
         }
-        mService.mDisplaySettings.setUserRotation(mDisplayContent, userRotationMode, userRotation);
+        mService.mDisplayWindowSettings.setUserRotation(mDisplayContent, userRotationMode,
+                userRotation);
         if (changed) {
             mService.updateRotation(true /* alwaysSendConfiguration */,
                     false /* forceRelayout */);
diff --git a/services/core/java/com/android/server/wm/DisplaySettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
similarity index 70%
rename from services/core/java/com/android/server/wm/DisplaySettings.java
rename to services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 624fbc7..f7dfd3f 100644
--- a/services/core/java/com/android/server/wm/DisplaySettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -16,6 +16,10 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
+
 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
 import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
@@ -52,8 +56,8 @@
 /**
  * Current persistent settings about a display
  */
-class DisplaySettings {
-    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplaySettings" : TAG_WM;
+class DisplayWindowSettings {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayWindowSettings" : TAG_WM;
 
     private final WindowManagerService mService;
     private final AtomicFile mFile;
@@ -72,9 +76,13 @@
         private int mForcedHeight;
         private int mForcedDensity;
         private int mForcedScalingMode = FORCE_SCALING_MODE_AUTO;
+        private int mRemoveContentMode = REMOVE_CONTENT_MODE_UNDEFINED;
+        private boolean mShouldShowWithInsecureKeyguard = false;
+        private boolean mShouldShowSystemDecors = false;
+        private boolean mShouldShowIme = false;
 
-        private Entry(String _name) {
-            mName = _name;
+        private Entry(String name) {
+            mName = name;
         }
 
         /** @return {@code true} if all values are default. */
@@ -85,16 +93,20 @@
                     && mUserRotationMode == WindowManagerPolicy.USER_ROTATION_FREE
                     && mUserRotation == Surface.ROTATION_0
                     && mForcedWidth == 0 && mForcedHeight == 0 && mForcedDensity == 0
-                    && mForcedScalingMode == FORCE_SCALING_MODE_AUTO;
+                    && mForcedScalingMode == FORCE_SCALING_MODE_AUTO
+                    && mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED
+                    && !mShouldShowWithInsecureKeyguard
+                    && !mShouldShowSystemDecors
+                    && !mShouldShowIme;
         }
     }
 
-    DisplaySettings(WindowManagerService service) {
+    DisplayWindowSettings(WindowManagerService service) {
         this(service, new File(Environment.getDataDirectory(), "system"));
     }
 
     @VisibleForTesting
-    DisplaySettings(WindowManagerService service, File folder) {
+    DisplayWindowSettings(WindowManagerService service, File folder) {
         mService = service;
         mFile = new AtomicFile(new File(folder, "display_settings.xml"), "wm-displays");
         readSettings();
@@ -195,6 +207,114 @@
         return windowingMode;
     }
 
+    int getWindowingModeLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        return getWindowingModeLocked(entry, dc.getDisplayId());
+    }
+
+    void setWindowingModeLocked(DisplayContent dc, int mode) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mWindowingMode = mode;
+        dc.setWindowingMode(mode);
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    int getRemoveContentModeLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null || entry.mRemoveContentMode == REMOVE_CONTENT_MODE_UNDEFINED) {
+            if (dc.isPrivate()) {
+                // For private displays by default content is destroyed on removal.
+                return REMOVE_CONTENT_MODE_DESTROY;
+            }
+            // For other displays by default content is moved to primary on removal.
+            return REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
+        }
+        return entry.mRemoveContentMode;
+    }
+
+    void setRemoveContentModeLocked(DisplayContent dc, int mode) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mRemoveContentMode = mode;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    boolean shouldShowWithInsecureKeyguardLocked(DisplayContent dc) {
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null) {
+            return false;
+        }
+        return entry.mShouldShowWithInsecureKeyguard;
+    }
+
+    void setShouldShowWithInsecureKeyguardLocked(DisplayContent dc, boolean shouldShow) {
+        if (!dc.isPrivate() && shouldShow) {
+            Slog.e(TAG, "Public display can't be allowed to show content when locked");
+            return;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mShouldShowWithInsecureKeyguard = shouldShow;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    boolean shouldShowSystemDecorsLocked(DisplayContent dc) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
+            // For default display should show system decors.
+            return true;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null) {
+            return false;
+        }
+        return entry.mShouldShowSystemDecors;
+    }
+
+    void setShouldShowSystemDecorsLocked(DisplayContent dc, boolean shouldShow) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
+            Slog.e(TAG, "Default display should show system decors");
+            return;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mShouldShowSystemDecors = shouldShow;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
+    boolean shouldShowImeLocked(DisplayContent dc) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY) {
+            // For default display should shows IME.
+            return true;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getEntry(displayInfo);
+        if (entry == null) {
+            return false;
+        }
+        return entry.mShouldShowIme;
+    }
+
+    void setShouldShowImeLocked(DisplayContent dc, boolean shouldShow) {
+        if (dc.getDisplayId() == Display.DEFAULT_DISPLAY && !shouldShow) {
+            Slog.e(TAG, "Default display should show IME");
+            return;
+        }
+
+        final DisplayInfo displayInfo = dc.getDisplayInfo();
+        final Entry entry = getOrCreateEntry(displayInfo);
+        entry.mShouldShowIme = shouldShow;
+        writeSettingsIfNeeded(entry, displayInfo);
+    }
+
     void applySettingsToDisplayLocked(DisplayContent dc) {
         final DisplayInfo displayInfo = dc.getDisplayInfo();
         final Entry entry = getEntry(displayInfo);
@@ -292,13 +412,26 @@
 
     private int getIntAttribute(XmlPullParser parser, String name, int defaultValue) {
         try {
-            String str = parser.getAttributeValue(null, name);
+            final String str = parser.getAttributeValue(null, name);
             return str != null ? Integer.parseInt(str) : defaultValue;
         } catch (NumberFormatException e) {
             return defaultValue;
         }
     }
 
+    private boolean getBooleanAttribute(XmlPullParser parser, String name) {
+        return getBooleanAttribute(parser, name, false /* defaultValue */);
+    }
+
+    private boolean getBooleanAttribute(XmlPullParser parser, String name, boolean defaultValue) {
+        try {
+            final String str = parser.getAttributeValue(null, name);
+            return str != null ? Boolean.parseBoolean(str) : defaultValue;
+        } catch (NumberFormatException e) {
+            return defaultValue;
+        }
+    }
+
     private void readDisplay(XmlPullParser parser) throws NumberFormatException,
             XmlPullParserException, IOException {
         String name = parser.getAttributeValue(null, "name");
@@ -319,6 +452,12 @@
             entry.mForcedDensity = getIntAttribute(parser, "forcedDensity");
             entry.mForcedScalingMode = getIntAttribute(parser, "forcedScalingMode",
                     FORCE_SCALING_MODE_AUTO);
+            entry.mRemoveContentMode = getIntAttribute(parser, "removeContentMode",
+                    REMOVE_CONTENT_MODE_UNDEFINED);
+            entry.mShouldShowWithInsecureKeyguard = getBooleanAttribute(parser,
+                    "shouldShowWithInsecureKeyguard");
+            entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
+            entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
             mEntries.put(name, entry);
         }
         XmlUtils.skipCurrentTag(parser);
@@ -387,6 +526,21 @@
                     out.attribute(null, "forcedScalingMode",
                             Integer.toString(entry.mForcedScalingMode));
                 }
+                if (entry.mRemoveContentMode != REMOVE_CONTENT_MODE_UNDEFINED) {
+                    out.attribute(null, "removeContentMode",
+                            Integer.toString(entry.mRemoveContentMode));
+                }
+                if (entry.mShouldShowWithInsecureKeyguard) {
+                    out.attribute(null, "shouldShowWithInsecureKeyguard",
+                            Boolean.toString(entry.mShouldShowWithInsecureKeyguard));
+                }
+                if (entry.mShouldShowSystemDecors) {
+                    out.attribute(null, "shouldShowSystemDecors",
+                            Boolean.toString(entry.mShouldShowSystemDecors));
+                }
+                if (entry.mShouldShowIme) {
+                    out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
+                }
                 out.endTag(null, "display");
             }
 
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 8c0c073..01b05c3 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -217,7 +217,7 @@
 
         if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Adding display=" + display);
 
-        mService.mDisplaySettings.applySettingsToDisplayLocked(dc);
+        mService.mDisplayWindowSettings.applySettingsToDisplayLocked(dc);
 
         if (mService.mDisplayManagerInternal != null) {
             mService.mDisplayManagerInternal.setDisplayInfoOverrideFromWindowManager(
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e4444e2..02904d4 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
@@ -62,6 +63,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
 import static android.view.WindowManagerGlobal.RELAYOUT_DEFER_SURFACE_DESTROY;
 import static android.view.WindowManagerGlobal.RELAYOUT_RES_SURFACE_CHANGED;
 
@@ -118,6 +120,7 @@
 import android.app.IActivityManager;
 import android.app.IActivityTaskManager;
 import android.app.IAssistDataReceiver;
+import android.app.WindowConfiguration;
 import android.app.admin.DevicePolicyCache;
 import android.content.BroadcastReceiver;
 import android.content.ContentResolver;
@@ -215,6 +218,7 @@
 import android.view.WindowContentFrameStats;
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
+import android.view.WindowManager.RemoveContentMode;
 import android.view.WindowManager.TransitionType;
 import android.view.WindowManagerGlobal;
 import android.view.WindowManagerPolicyConstants.PointerEventListener;
@@ -428,7 +432,7 @@
     final AppOpsManager mAppOps;
     final PackageManagerInternal mPmInternal;
 
-    final DisplaySettings mDisplaySettings;
+    final DisplayWindowSettings mDisplayWindowSettings;
 
     /** If the system should display notifications for apps displaying an alert window. */
     boolean mShowAlertWindowNotifications = true;
@@ -914,7 +918,7 @@
                 com.android.internal.R.bool.config_disableTransitionAnimation);
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
-        mDisplaySettings = new DisplaySettings(this);
+        mDisplayWindowSettings = new DisplayWindowSettings(this);
 
         mPolicy = policy;
         mAnimator = new WindowAnimator(this);
@@ -5091,7 +5095,7 @@
         displayInfo.overscanRight = right;
         displayInfo.overscanBottom = bottom;
 
-        mDisplaySettings.setOverscanLocked(displayInfo, left, top, right, bottom);
+        mDisplayWindowSettings.setOverscanLocked(displayInfo, left, top, right, bottom);
 
         reconfigureDisplayLocked(displayContent);
     }
@@ -6615,6 +6619,193 @@
     }
 
     @Override
+    public int getWindowingMode(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getWindowingMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get windowing mode of a display that does not exist: "
+                        + displayId);
+                return WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+            }
+            return mDisplayWindowSettings.getWindowingModeLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setWindowingMode(int displayId, int mode) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setWindowingMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set windowing mode to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setWindowingModeLocked(displayContent, mode);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public @RemoveContentMode int getRemoveContentMode(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "getRemoveContentMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get remove mode of a display that does not exist: "
+                        + displayId);
+                return REMOVE_CONTENT_MODE_UNDEFINED;
+            }
+            return mDisplayWindowSettings.getRemoveContentModeLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setRemoveContentMode(int displayId, @RemoveContentMode int mode) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setRemoveContentMode()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set remove mode to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setRemoveContentModeLocked(displayContent, mode);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public boolean shouldShowWithInsecureKeyguard(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowWithInsecureKeyguard()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get flag of a display that does not exist: "
+                        + displayId);
+                return false;
+            }
+            return mDisplayWindowSettings.shouldShowWithInsecureKeyguardLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW,
+                "setShouldShowWithInsecureKeyguard()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set flag to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setShouldShowWithInsecureKeyguardLocked(displayContent,
+                    shouldShow);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public boolean shouldShowSystemDecors(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowSystemDecors()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get system decors flag of a display that does "
+                        + "not exist: " + displayId);
+                return false;
+            }
+            return mDisplayWindowSettings.shouldShowSystemDecorsLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowSystemDecors()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set system decors flag to a display that does "
+                        + "not exist: " + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setShouldShowSystemDecorsLocked(displayContent, shouldShow);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
+    public boolean shouldShowIme(int displayId) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "shouldShowIme()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to get IME flag of a display that does not exist: "
+                        + displayId);
+                return false;
+            }
+            return mDisplayWindowSettings.shouldShowImeLocked(displayContent);
+        }
+    }
+
+    @Override
+    public void setShouldShowIme(int displayId, boolean shouldShow) {
+        if (!checkCallingPermission(INTERNAL_SYSTEM_WINDOW, "setShouldShowIme()")) {
+            throw new SecurityException("Requires INTERNAL_SYSTEM_WINDOW permission");
+        }
+
+        synchronized (mGlobalLock) {
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, null);
+            if (displayContent == null) {
+                Slog.w(TAG_WM, "Attempted to set IME flag to a display that does not exist: "
+                        + displayId);
+                return;
+            }
+
+            mDisplayWindowSettings.setShouldShowImeLocked(displayContent, shouldShow);
+
+            reconfigureDisplayLocked(displayContent);
+        }
+    }
+
+    @Override
     public void registerShortcutKey(long shortcutCode, IShortcutService shortcutKeyReceiver)
             throws RemoteException {
         if (!checkCallingPermission(REGISTER_WINDOW_MANAGER_LISTENERS, "registerShortcutKey")) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
similarity index 79%
rename from services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
rename to services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 5808bc9..b823e70 100644
--- a/services/tests/servicestests/src/com/android/server/wm/DisplaySettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_DESTROY;
+import static android.view.WindowManager.REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY;
+
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
 import static org.junit.Assert.assertEquals;
@@ -43,20 +46,23 @@
 import java.io.File;
 
 /**
- * Tests for the {@link DisplaySettings} class.
+ * Tests for the {@link DisplayWindowSettings} class.
  *
  * Build/Install/Run:
- *  atest FrameworksServicesTests:DisplaySettingsTests
+ *  atest FrameworksServicesTests:DisplayWindowSettingsTests
  */
 @SmallTest
 @Presubmit
-public class DisplaySettingsTests extends WindowTestsBase {
+public class DisplayWindowSettingsTests extends WindowTestsBase {
 
     private static final File TEST_FOLDER = getInstrumentation().getTargetContext().getCacheDir();
-    private DisplaySettings mTarget;
+    private DisplayWindowSettings mTarget;
+
+    DisplayInfo mPrivateDisplayInfo;
 
     private DisplayContent mPrimaryDisplay;
     private DisplayContent mSecondaryDisplay;
+    private DisplayContent mPrivateDisplay;
 
     @Before
     public void setUp() throws Exception {
@@ -66,11 +72,17 @@
         mWm.setIsPc(false);
         mWm.setForceDesktopModeOnExternalDisplays(false);
 
-        mTarget = new DisplaySettings(mWm, TEST_FOLDER);
+        mTarget = new DisplayWindowSettings(mWm, TEST_FOLDER);
 
         mPrimaryDisplay = mWm.getDefaultDisplayContentLocked();
         mSecondaryDisplay = mDisplayContent;
         assertNotEquals(Display.DEFAULT_DISPLAY, mSecondaryDisplay.getDisplayId());
+
+        mPrivateDisplayInfo = new DisplayInfo(mDisplayInfo);
+        mPrivateDisplayInfo.flags |= Display.FLAG_PRIVATE;
+        mPrivateDisplay = createNewDisplay(mPrivateDisplayInfo);
+        assertNotEquals(Display.DEFAULT_DISPLAY, mPrivateDisplay.getDisplayId());
+        assertNotEquals(mSecondaryDisplay.getDisplayId(), mPrivateDisplay.getDisplayId());
     }
 
     @After
@@ -261,6 +273,67 @@
     }
 
     @Test
+    public void testPrivateDisplayDefaultToDestroyContent() {
+        assertEquals(REMOVE_CONTENT_MODE_DESTROY,
+                mTarget.getRemoveContentModeLocked(mPrivateDisplay));
+    }
+
+    @Test
+    public void testPublicDisplayDefaultToMoveToPrimary() {
+        assertEquals(REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
+                mTarget.getRemoveContentModeLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testDefaultToNotShowWithInsecureKeyguard() {
+        assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
+        assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testPublicDisplayNotAllowSetShouldShowWithInsecureKeyguard() {
+        mTarget.setShouldShowWithInsecureKeyguardLocked(mSecondaryDisplay, true);
+
+        assertFalse(mTarget.shouldShowWithInsecureKeyguardLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testPrivateDisplayAllowSetShouldShowWithInsecureKeyguard() {
+        mTarget.setShouldShowWithInsecureKeyguardLocked(mPrivateDisplay, true);
+
+        assertTrue(mTarget.shouldShowWithInsecureKeyguardLocked(mPrivateDisplay));
+    }
+
+    @Test
+    public void testPrimaryDisplayShouldShowSystemDecors() {
+        assertTrue(mTarget.shouldShowSystemDecorsLocked(mPrimaryDisplay));
+
+        mTarget.setShouldShowSystemDecorsLocked(mPrimaryDisplay, false);
+
+        // Default display should show system decors
+        assertTrue(mTarget.shouldShowSystemDecorsLocked(mPrimaryDisplay));
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToNotShowSystemDecors() {
+        assertFalse(mTarget.shouldShowSystemDecorsLocked(mSecondaryDisplay));
+    }
+
+    @Test
+    public void testPrimaryDisplayShouldShowIme() {
+        assertTrue(mTarget.shouldShowImeLocked(mPrimaryDisplay));
+
+        mTarget.setShouldShowImeLocked(mPrimaryDisplay, false);
+
+        assertTrue(mTarget.shouldShowImeLocked(mPrimaryDisplay));
+    }
+
+    @Test
+    public void testSecondaryDisplayDefaultToNotShowIme() {
+        assertFalse(mTarget.shouldShowImeLocked(mSecondaryDisplay));
+    }
+
+    @Test
     public void testPersistUserRotationModeInSameInstance() {
         mTarget.setUserRotation(mSecondaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
                 Surface.ROTATION_90);
@@ -317,11 +390,11 @@
 
     /**
      * This method helps to ensure read and write persistent settings successfully because the
-     * constructor of {@link DisplaySettings} should read the persistent file from the given path
-     * that also means the previous state must be written correctly.
+     * constructor of {@link DisplayWindowSettings} should read the persistent file from the given
+     * path that also means the previous state must be written correctly.
      */
     private void applySettingsToDisplayByNewInstance(DisplayContent display) {
-        new DisplaySettings(mWm, TEST_FOLDER).applySettingsToDisplayLocked(display);
+        new DisplayWindowSettings(mWm, TEST_FOLDER).applySettingsToDisplayLocked(display);
     }
 
     private static boolean deleteRecursively(File file) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
index 945cbb9..2abe64d 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowTestsBase.java
@@ -354,9 +354,14 @@
 
     /** Creates a {@link DisplayContent} and adds it to the system. */
     DisplayContent createNewDisplay() {
+        return createNewDisplay(mDisplayInfo);
+    }
+
+    /** Creates a {@link DisplayContent} and adds it to the system. */
+    DisplayContent createNewDisplay(DisplayInfo displayInfo) {
         final int displayId = sNextDisplayId++;
         final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
-                mDisplayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
+                displayInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
         synchronized (mWm.mGlobalLock) {
             return new DisplayContent(display, mWm, mWallpaperController,
                     mock(DisplayWindowController.class));