From 8753ad366b02f661c438afba8207fc0b67e10d9c Mon Sep 17 00:00:00 2001 From: Chilun Date: Tue, 9 Oct 2018 15:56:45 +0800 Subject: [PATCH] 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 --- api/test-current.txt | 6 + .../hardware/display/DisplayManager.java | 3 + core/java/android/view/Display.java | 6 + core/java/android/view/DisplayInfo.java | 1 + core/java/android/view/IWindowManager.aidl | 116 +++++++++++ core/java/android/view/WindowManager.java | 71 +++++++ core/java/android/view/WindowManagerImpl.java | 26 +++ .../server/display/DisplayDeviceInfo.java | 3 + .../com/android/server/wm/DisplayContent.java | 6 +- .../android/server/wm/DisplayRotation.java | 3 +- ...ttings.java => DisplayWindowSettings.java} | 170 ++++++++++++++- .../server/wm/RootWindowContainer.java | 2 +- .../server/wm/WindowManagerService.java | 197 +++++++++++++++++- ...s.java => DisplayWindowSettingsTests.java} | 89 +++++++- .../android/server/wm/WindowTestsBase.java | 7 +- 15 files changed, 681 insertions(+), 25 deletions(-) rename services/core/java/com/android/server/wm/{DisplaySettings.java => DisplayWindowSettings.java} (70%) rename services/tests/servicestests/src/com/android/server/wm/{DisplaySettingsTests.java => DisplayWindowSettingsTests.java} (79%) diff --git a/api/test-current.txt b/api/test-current.txt index b2cf4c897e07a..5dc2945ab7080 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 01ef58e987d71..82e765dee4476 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 719a401ce0cf9..3f14379c9bc9c 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 34bcbdd94041d..43de1f89649cc 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 CREATOR = new Creator() { diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index 5c07f44cec617..c836c9ec0defc 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. + *

+ * 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. + *

+ * + * @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. + *

+ * This mode indicates what actions should be performed with the display's content when it is + * removed. + *

+ * + * @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. + *

+ * This flag identifies secondary displays that will continue showing content if keyguard can be + * dismissed without entering credentials. + *

+ * An example of usage is a virtual display which content is displayed on external hardware + * display that is not visible to the system directly. + *

+ * + * @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. + *

+ * System decors include status bar, navigation bar, launcher. + *

+ * + * @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. + *

+ * System decors include status bar, navigation bar, launcher. + *

+ * + * @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 2d77cb4f3aca0..8d8a37061035d 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -314,6 +314,36 @@ public interface WindowManager extends ViewManager { @Retention(RetentionPolicy.SOURCE) @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} @@ -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. + *

+ * System decors include status bar, navigation bar, launcher. + *

+ * + * @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 2339d35f73176..a102f6c8a74dd 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 c51dc52b0515d..ab64f61a3b221 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 e20793ec3ffc1..b01d67d84f957 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 { 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 e4444e29e4900..02904d413b357 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); } @@ -6614,6 +6618,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 { 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 5808bc9999373..b823e706a5863 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 @@ -260,6 +272,67 @@ public class DisplaySettingsTests extends WindowTestsBase { assertEquals(Surface.ROTATION_0, mSecondaryDisplay.getDisplayRotation().getUserRotation()); } + @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, @@ -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 945cbb91b0294..2abe64dd80a47 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));