diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 6934e5c3bcc1e..6a1584374251c 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -493,6 +493,32 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { * @return int An arbitrary integer used to order windows, with lower numbers below higher ones. */ default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow) { + return getWindowLayerFromTypeLw(type, canAddInternalSystemWindow, + false /* roundedCornerOverlay */); + } + + /** + * Returns the layer assignment for the window type. Allows you to control how different + * kinds of windows are ordered on-screen. + * + * @param type The type of window being assigned. + * @param canAddInternalSystemWindow If the owner window associated with the type we are + * evaluating can add internal system windows. I.e they have + * {@link Manifest.permission#INTERNAL_SYSTEM_WINDOW}. If true, alert window + * types {@link android.view.WindowManager.LayoutParams#isSystemAlertWindowType(int)} + * can be assigned layers greater than the layer for + * {@link android.view.WindowManager.LayoutParams#TYPE_APPLICATION_OVERLAY} Else, their + * layers would be lesser. + * @param roundedCornerOverlay {#code true} to indicate that the owner window is rounded corner + * overlay. + * @return int An arbitrary integer used to order windows, with lower numbers below higher ones. + */ + default int getWindowLayerFromTypeLw(int type, boolean canAddInternalSystemWindow, + boolean roundedCornerOverlay) { + // Always put the rounded corner layer to the top most. + if (roundedCornerOverlay && canAddInternalSystemWindow) { + return getMaxWindowLayer(); + } if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) { return APPLICATION_LAYER; } @@ -595,8 +621,17 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { } } + // TODO(b/155340867): consider to remove the logic after using pure Surface for rounded corner + // overlay. + /** + * Returns the max window layer. + *

Note that the max window layer should be higher that the maximum value which reported + * by {@link #getWindowLayerFromTypeLw(int, boolean)} to contain rounded corner overlay.

+ * + * @see WindowManager.LayoutParams#PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY + */ default int getMaxWindowLayer() { - return 35; + return 36; } /** diff --git a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java index c8fadf62eb2f9..f505daa9b6283 100644 --- a/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java +++ b/services/core/java/com/android/server/wm/DisplayAreaPolicyBuilder.java @@ -365,7 +365,7 @@ class DisplayAreaPolicyBuilder { */ private void build(@Nullable List displayAreaGroupHierarchyBuilders) { final WindowManagerPolicy policy = mRoot.mWmService.mPolicy; - final int maxWindowLayerCount = policy.getMaxWindowLayer(); + final int maxWindowLayerCount = policy.getMaxWindowLayer() + 1; final DisplayArea.Tokens[] displayAreaForLayer = new DisplayArea.Tokens[maxWindowLayerCount]; final Map>> featureAreas = @@ -560,6 +560,7 @@ class DisplayAreaPolicyBuilder { private final int mId; private final boolean[] mLayers; private NewDisplayAreaSupplier mNewDisplayAreaSupplier = DisplayArea::new; + private boolean mExcludeRoundedCorner = true; /** * Builds a new feature that applies to a set of window types as specified by the @@ -578,7 +579,7 @@ class DisplayAreaPolicyBuilder { mPolicy = policy; mName = name; mId = id; - mLayers = new boolean[mPolicy.getMaxWindowLayer()]; + mLayers = new boolean[mPolicy.getMaxWindowLayer() + 1]; } /** @@ -633,7 +634,18 @@ class DisplayAreaPolicyBuilder { return this; } + // TODO(b/155340867): consider to remove the logic after using pure Surface for rounded + // corner overlay. + Builder setExcludeRoundedCornerOverlay(boolean excludeRoundedCorner) { + mExcludeRoundedCorner = excludeRoundedCorner; + return this; + } + Feature build() { + if (mExcludeRoundedCorner) { + // Always put the rounded corner layer to the top most layer. + mLayers[mPolicy.getMaxWindowLayer()] = false; + } return new Feature(mName, mId, mLayers.clone(), mNewDisplayAreaSupplier); } diff --git a/services/core/java/com/android/server/wm/RootDisplayArea.java b/services/core/java/com/android/server/wm/RootDisplayArea.java index 393055eab111d..505af05ed642f 100644 --- a/services/core/java/com/android/server/wm/RootDisplayArea.java +++ b/services/core/java/com/android/server/wm/RootDisplayArea.java @@ -115,15 +115,11 @@ class RootDisplayArea extends DisplayArea { @Nullable DisplayArea.Tokens findAreaForToken(int windowType, boolean ownerCanManageAppTokens, boolean roundedCornerOverlay) { - // TODO(b/159767464): cover TYPE_INPUT_METHOD(_DIALOG) case here. mAreaForLayer doesn't - // contain IME container. int windowLayerFromType = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, - ownerCanManageAppTokens); + ownerCanManageAppTokens, roundedCornerOverlay); if (windowLayerFromType == APPLICATION_LAYER) { throw new IllegalArgumentException( "There shouldn't be WindowToken on APPLICATION_LAYER"); - } else if (roundedCornerOverlay) { - windowLayerFromType = mAreaForLayer.length - 1; } return mAreaForLayer[windowLayerFromType]; } diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 34875ed70889e..9e0fee3927c3c 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -827,15 +827,15 @@ class WindowToken extends WindowContainer { * system bars, or in other words extend outside of the "Decor Frame" */ boolean canLayerAboveSystemBars() { - int layer = mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, - mOwnerCanManageAppTokens); + int layer = getWindowLayerFromType(); int navLayer = mWmService.mPolicy.getWindowLayerFromTypeLw(TYPE_NAVIGATION_BAR, mOwnerCanManageAppTokens); return mOwnerCanManageAppTokens && (layer > navLayer); } int getWindowLayerFromType() { - return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens); + return mWmService.mPolicy.getWindowLayerFromTypeLw(windowType, mOwnerCanManageAppTokens, + mRoundedCornerOverlay); } int getOwnerUid() { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java index e47913fba7abc..910e84c9f7e22 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java @@ -22,6 +22,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; +import static android.view.WindowManager.LayoutParams.TYPE_POINTER; import static android.view.WindowManager.LayoutParams.TYPE_PRESENTATION; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; @@ -667,6 +668,15 @@ public class DisplayAreaPolicyBuilderTest { assertThat(token2.isDescendantOf(mGroupRoot2)).isTrue(); } + @Test + public void testFeatureNotThrowArrayIndexOutOfBoundsException() { + final Feature feature1 = new Feature.Builder(mWms.mPolicy, "feature1", + FEATURE_VENDOR_FIRST + 5) + .all() + .except(TYPE_POINTER) + .build(); + } + private static Resources resourcesWithProvider(String provider) { Resources mock = mock(Resources.class); when(mock.getString(