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));