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/api/test-current.txt b/api/test-current.txt
index b2cf4c8..5dc2945 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1636,6 +1636,12 @@
     method public boolean unregisterFrameCommitCallback(java.lang.Runnable);
   }
 
+  public abstract interface WindowManager implements android.view.ViewManager {
+    method public abstract void setShouldShowIme(int, boolean);
+    method public abstract void setShouldShowWithInsecureKeyguard(int, boolean);
+    method public abstract void setShouldShowSystemDecors(int, boolean);
+  }
+
   public static class WindowManager.LayoutParams extends android.view.ViewGroup.LayoutParams implements android.os.Parcelable {
     field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int PRIVATE_FLAG_NO_MOVE_ANIMATION = 64; // 0x40
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 01ef58e..82e765d 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -263,6 +263,7 @@
      * @see KeyguardManager#isDeviceLocked()
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard
     // TODO: Update name and documentation and un-hide the flag. Don't change the value before that.
     public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
 
@@ -295,6 +296,7 @@
      * @see #createVirtualDisplay
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY
     public static final int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 8;
 
     /**
@@ -304,6 +306,7 @@
      * @see #createVirtualDisplay
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9;
 
     /** @hide */
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 719a401..3f14379 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -218,6 +218,7 @@
      * @see #getFlags
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard
     public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5;
 
     /**
@@ -230,6 +231,7 @@
      * @see #supportsSystemDecorations
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors
     public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 6;
 
     /**
@@ -384,6 +386,7 @@
      *
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY
     public static final int REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY = 0;
     /**
      * Indicates that when display is removed, all its stacks and tasks will be removed, all
@@ -391,6 +394,7 @@
      *
      * @hide
      */
+    // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY
     public static final int REMOVE_MODE_DESTROY_CONTENT = 1;
 
     /**
@@ -881,6 +885,7 @@
      * @see #REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY
      * @see #REMOVE_MODE_DESTROY_CONTENT
      */
+    // TODO (b/114338689): Remove the method and use IWindowManager#getRemoveContentMode
     public int getRemoveMode() {
         return mDisplayInfo.removeMode;
     }
@@ -891,6 +896,7 @@
      * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
      * @hide
      */
+    // TODO (b/114338689): Remove the method and use IWindowManager#shouldShowSystemDecors
     public boolean supportsSystemDecorations() {
         return (mDisplayInfo.flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0;
     }
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 34bcbdd..43de1f8 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -266,6 +266,7 @@
      *
      * @see Display#getRemoveMode()
      */
+    // TODO (b/114338689): Remove the flag and use IWindowManager#getRemoveContentMode
     public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
 
     public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 5c07f44..c836c9e 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -432,4 +432,120 @@
      * @param displayId The id of the display.
      */
     void dontOverrideDisplayInfo(int displayId);
+
+    /**
+     * Gets the windowing mode of the display.
+     *
+     * @param displayId The id of the display.
+     * @return {@link WindowConfiguration.WindowingMode}
+     */
+    int getWindowingMode(int displayId);
+
+    /**
+     * Sets the windowing mode of the display.
+     *
+     * @param displayId The id of the display.
+     * @param mode {@link WindowConfiguration.WindowingMode}
+     */
+    void setWindowingMode(int displayId, int mode);
+
+    /**
+     * Gets current remove content mode of the display.
+     * <p>
+     * What actions should be performed with the display's content when it is removed. Default
+     * behavior for public displays in this case is to move all activities to the primary display
+     * and make it focused. For private display is to destroy all activities.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @return The remove content mode of the display.
+     * @see WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY
+     * @see WindowManager#REMOVE_CONTENT_MODE_DESTROY
+     */
+    int getRemoveContentMode(int displayId);
+
+    /**
+     * Sets the remove content mode of the display.
+     * <p>
+     * This mode indicates what actions should be performed with the display's content when it is
+     * removed.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @param mode Remove content mode.
+     * @see WindowManager#REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY
+     * @see WindowManager#REMOVE_CONTENT_MODE_DESTROY
+     */
+    void setRemoveContentMode(int displayId, int mode);
+
+    /**
+     * Indicates that the display should show its content when non-secure keyguard is shown.
+     * <p>
+     * This flag identifies secondary displays that will continue showing content if keyguard can be
+     * dismissed without entering credentials.
+     * </p><p>
+     * An example of usage is a virtual display which content is displayed on external hardware
+     * display that is not visible to the system directly.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @return {@code true} if the display should show its content when non-secure keyguard is
+     *         shown.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    boolean shouldShowWithInsecureKeyguard(int displayId);
+
+    /**
+     * Sets that the display should show its content when non-secure keyguard is shown.
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show its content when non-secure keyguard
+     *                  is shown.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow);
+
+    /**
+     * Indicates the display should show system decors.
+     * <p>
+     * System decors include status bar, navigation bar, launcher.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @return {@code true} if the display should show system decors.
+     */
+    boolean shouldShowSystemDecors(int displayId);
+
+    /**
+     * Sets that the display should show system decors.
+     * <p>
+     * System decors include status bar, navigation bar, launcher.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show system decors.
+     */
+    void setShouldShowSystemDecors(int displayId, boolean shouldShow);
+
+    /**
+     * Indicates that the display should show IME.
+     *
+     * @param displayId The id of the display.
+     * @return {@code true} if the display should show IME.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    boolean shouldShowIme(int displayId);
+
+    /**
+     * Sets that the display should show IME.
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show IME.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     */
+    void setShouldShowIme(int displayId, boolean shouldShow);
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 2d77cb4..8d8a370 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -315,6 +315,36 @@
     @interface TransitionFlags {}
 
     /**
+     * Remove content mode: Indicates remove content mode is currently not defined.
+     * @hide
+     */
+    int REMOVE_CONTENT_MODE_UNDEFINED = 0;
+
+    /**
+     * Remove content mode: Indicates that when display is removed, all its activities will be moved
+     * to the primary display and the topmost activity should become focused.
+     * @hide
+     */
+    int REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY = 1;
+
+    /**
+     * Remove content mode: Indicates that when display is removed, all its stacks and tasks will be
+     * removed, all activities will be destroyed according to the usual lifecycle.
+     * @hide
+     */
+    int REMOVE_CONTENT_MODE_DESTROY = 2;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = { "REMOVE_CONTENT_MODE_" }, value = {
+            REMOVE_CONTENT_MODE_UNDEFINED,
+            REMOVE_CONTENT_MODE_MOVE_TO_PRIMARY,
+            REMOVE_CONTENT_MODE_DESTROY,
+    })
+    @interface RemoveContentMode {}
+
+    /**
      * Exception that is thrown when trying to add view whose
      * {@link LayoutParams} {@link LayoutParams#token}
      * is invalid.
@@ -422,6 +452,47 @@
     @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public Region getCurrentImeTouchRegion();
 
+    /**
+     * Sets that the display should show its content when non-secure keyguard is shown.
+     *
+     * @param displayId Display ID.
+     * @param shouldShow Indicates that the display should show its content when non-secure keyguard
+     *                  is shown.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     * @hide
+     */
+    @TestApi
+    default void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
+    }
+
+    /**
+     * Sets that the display should show system decors.
+     * <p>
+     * System decors include status bar, navigation bar, launcher.
+     * </p>
+     *
+     * @param displayId The id of the display.
+     * @param shouldShow Indicates that the display should show system decors.
+     * @hide
+     */
+    @TestApi
+    default void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
+    }
+
+    /**
+     * Sets that the display should show IME.
+     *
+     * @param displayId Display ID.
+     * @param shouldShow Indicates that the display should show IME.
+     * @see KeyguardManager#isDeviceSecure()
+     * @see KeyguardManager#isDeviceLocked()
+     * @hide
+     */
+    @TestApi
+    default void setShouldShowIme(int displayId, boolean shouldShow) {
+    }
+
     public static class LayoutParams extends ViewGroup.LayoutParams implements Parcelable {
         /**
          * X position for this window.  With the default gravity it is ignored.
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 2339d35..a102f6c 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -157,4 +157,30 @@
         }
         return null;
     }
+
+    @Override
+    public void setShouldShowWithInsecureKeyguard(int displayId, boolean shouldShow) {
+        try {
+            WindowManagerGlobal.getWindowManagerService()
+                    .setShouldShowWithInsecureKeyguard(displayId, shouldShow);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void setShouldShowSystemDecors(int displayId, boolean shouldShow) {
+        try {
+            WindowManagerGlobal.getWindowManagerService()
+                    .setShouldShowSystemDecors(displayId, shouldShow);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void setShouldShowIme(int displayId, boolean shouldShow) {
+        try {
+            WindowManagerGlobal.getWindowManagerService().setShouldShowIme(displayId, shouldShow);
+        } catch (RemoteException e) {
+        }
+    }
 }
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));