diff options
| author | 2018-10-09 15:56:45 +0800 | |
|---|---|---|
| committer | 2018-11-10 16:49:56 +0800 | |
| commit | 8753ad366b02f661c438afba8207fc0b67e10d9c (patch) | |
| tree | 6962842e30abfe90409d63585969a8e4f8a33da3 | |
| parent | 5a19fd430e919c17e243e1bc355aeeae1711f6f1 (diff) | |
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
15 files changed, 681 insertions, 25 deletions
diff --git a/api/test-current.txt b/api/test-current.txt index b2cf4c897e07..5dc2945ab708 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -1636,6 +1636,12 @@ package android.view { 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 01ef58e987d7..82e765dee447 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -263,6 +263,7 @@ public final class DisplayManager { * @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 @@ public final class DisplayManager { * @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 @@ public final class DisplayManager { * @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 719a401ce0cf..3f14379c9bc9 100644 --- a/core/java/android/view/Display.java +++ b/core/java/android/view/Display.java @@ -218,6 +218,7 @@ public final class Display { * @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 @@ public final class Display { * @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 @@ public final class Display { * * @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 @@ public final class Display { * * @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 @@ public final class Display { * @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 @@ public final class Display { * @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 34bcbdd94041..43de1f89649c 100644 --- a/core/java/android/view/DisplayInfo.java +++ b/core/java/android/view/DisplayInfo.java @@ -266,6 +266,7 @@ public final class DisplayInfo implements Parcelable { * * @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 5c07f44cec61..c836c9ec0def 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -432,4 +432,120 @@ interface IWindowManager * @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 2d77cb4f3aca..8d8a37061035 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -315,6 +315,36 @@ public interface WindowManager extends ViewManager { @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 @@ public interface WindowManager extends ViewManager { @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 2339d35f7317..a102f6c8a74d 100644 --- a/core/java/android/view/WindowManagerImpl.java +++ b/core/java/android/view/WindowManagerImpl.java @@ -157,4 +157,30 @@ public final class WindowManagerImpl implements WindowManager { } 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 c51dc52b0515..ab64f61a3b22 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 @@ final class DisplayDeviceInfo { /** * 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 @@ final class DisplayDeviceInfo { * 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 e20793ec3ffc..b01d67d84f95 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo 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 9f98dc5ee5c7..6ab7090d1aae 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 @@ public class DisplayRotation { 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 index 624fbc79af83..f7dfd3ffc8bf 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 @@ import java.util.HashMap; /** * 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 @@ class DisplaySettings { 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 @@ class DisplaySettings { && 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 @@ class DisplaySettings { 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 @@ class DisplaySettings { 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 @@ class DisplaySettings { 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 @@ class DisplaySettings { 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 8c0c073ce11a..01b05c38df67 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 @@ class RootWindowContainer extends WindowContainer<DisplayContent> { 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 e4444e29e490..02904d413b35 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_STATUS_BAR; 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.AppOpsManager; 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.View; 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub 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 @@ public class WindowManagerService extends IWindowManager.Stub } @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 index 5808bc999937..b823e706a586 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 org.junit.Test; 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 @@ public class DisplaySettingsTests extends WindowTestsBase { 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 @@ public class DisplaySettingsTests extends WindowTestsBase { } @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 @@ public class DisplaySettingsTests extends WindowTestsBase { /** * 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 945cbb91b029..2abe64dd80a4 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 @@ class WindowTestsBase { /** 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)); |