diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index d0a7c26741c7f..a3564e99b3ea7 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -2156,15 +2156,6 @@ public interface WindowManager extends ViewManager { */ public static final int PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY = 0x00100000; - /** - * Flag to indicate that this window should be considered a screen decoration similar to the - * nav bar and status bar. This will cause this window to affect the window insets reported - * to other windows when it is visible. - * @hide - */ - @RequiresPermission(permission.STATUS_BAR_SERVICE) - public static final int PRIVATE_FLAG_IS_SCREEN_DECOR = 0x00400000; - /** * Flag to indicate that the status bar window is in a state such that it forces showing * the navigation bar unless the navigation bar window is explicitly set to @@ -2270,7 +2261,6 @@ public interface WindowManager extends ViewManager { PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE, SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS, PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, - PRIVATE_FLAG_IS_SCREEN_DECOR, PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC, PRIVATE_FLAG_USE_BLAST, @@ -2357,10 +2347,6 @@ public interface WindowManager extends ViewManager { mask = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, equals = PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY, name = "IS_ROUNDED_CORNERS_OVERLAY"), - @ViewDebug.FlagToString( - mask = PRIVATE_FLAG_IS_SCREEN_DECOR, - equals = PRIVATE_FLAG_IS_SCREEN_DECOR, - name = "IS_SCREEN_DECOR"), @ViewDebug.FlagToString( mask = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, equals = PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION, diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index f14a2ee8e7ee6..3e31dceb281da 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -66,7 +66,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BA import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_SHOW_STATUS_BAR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INSET_PARENT_FRAME_BY_IME; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD; @@ -279,7 +278,6 @@ public class DisplayPolicy { private volatile boolean mKeyguardDrawComplete; private volatile boolean mWindowManagerDrawComplete; - private final ArraySet mScreenDecorWindows = new ArraySet<>(); private WindowState mStatusBar = null; private WindowState mNotificationShade = null; private final int[] mStatusBarHeightForRotation = new int[4]; @@ -864,19 +862,7 @@ public class DisplayPolicy { * @param attrs The window layout parameters to be modified. These values * are modified in-place. */ - public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs, - int callingPid, int callingUid) { - - final boolean isScreenDecor = (attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0; - if (mScreenDecorWindows.contains(win)) { - if (!isScreenDecor) { - // No longer has the flag set, so remove from the set. - mScreenDecorWindows.remove(win); - } - } else if (isScreenDecor && hasStatusBarServicePermission(callingPid, callingUid)) { - mScreenDecorWindows.add(win); - } - + public void adjustWindowParamsLw(WindowState win, WindowManager.LayoutParams attrs) { switch (attrs.type) { case TYPE_SYSTEM_OVERLAY: case TYPE_SECURE_SYSTEM_OVERLAY: @@ -966,11 +952,6 @@ public class DisplayPolicy { * WindowManagerImpl.ADD_MULTIPLE_SINGLETON */ int validateAddingWindowLw(WindowManager.LayoutParams attrs, int callingPid, int callingUid) { - if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) { - mContext.enforcePermission( - android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid, - "DisplayPolicy"); - } if ((attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) != 0) { mContext.enforcePermission( android.Manifest.permission.INTERNAL_SYSTEM_WINDOW, callingPid, callingUid, @@ -1090,10 +1071,6 @@ public class DisplayPolicy { * @param attrs Information about the window to be added. */ void addWindowLw(WindowState win, WindowManager.LayoutParams attrs) { - if ((attrs.privateFlags & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0) { - mScreenDecorWindows.add(win); - } - switch (attrs.type) { case TYPE_NOTIFICATION_SHADE: mNotificationShade = win; @@ -1275,7 +1252,6 @@ public class DisplayPolicy { if (mLastFocusedWindow == win) { mLastFocusedWindow = null; } - mScreenDecorWindows.remove(win); } private int getStatusBarHeight(DisplayFrames displayFrames) { @@ -1457,14 +1433,12 @@ public class DisplayPolicy { } final int fl = attrs.flags; - final int pfl = attrs.privateFlags; final boolean layoutInScreenAndInsetDecor = (fl & FLAG_LAYOUT_IN_SCREEN) != 0 && (fl & FLAG_LAYOUT_INSET_DECOR) != 0; - final boolean screenDecor = (pfl & PRIVATE_FLAG_IS_SCREEN_DECOR) != 0; final DisplayFrames displayFrames = isFixedRotationTransforming ? windowToken.getFixedRotationTransformDisplayFrames() : mDisplayContent.mDisplayFrames; - if (layoutInScreenAndInsetDecor && !screenDecor) { + if (layoutInScreenAndInsetDecor) { outDisplayCutout.set( displayFrames.mDisplayCutout.calculateRelativeTo(outFrame).getDisplayCutout()); } else { @@ -1564,7 +1538,6 @@ public class DisplayPolicy { simulatedWindowFrames, barContentFrames, contentFrame -> layoutStatusBar(displayFrames, contentFrame)); } - layoutScreenDecorWindows(displayFrames, simulatedWindowFrames); } /** @@ -1585,7 +1558,6 @@ public class DisplayPolicy { layoutNavigationBar(displayFrames, uiMode, null /* simulatedContentFrame */); layoutStatusBar(displayFrames, null /* simulatedContentFrame */); - layoutScreenDecorWindows(displayFrames, null /* simulatedFrames */); } void updateHideNavInputEventReceiver() { @@ -1640,47 +1612,6 @@ public class DisplayPolicy { state.getSource(ITYPE_BOTTOM_DISPLAY_CUTOUT).setFrame(u.left, s.bottom, u.right, u.bottom); } - /** - * Layout the decor windows with {@link #PRIVATE_FLAG_IS_SCREEN_DECOR}. - * - * @param displayFrames The display frames to be layouted. - * @param simulatedFrames Non-null if the caller only needs the result of display frames (see - * {@link WindowState#mSimulatedWindowFrames}). - */ - private void layoutScreenDecorWindows(DisplayFrames displayFrames, - WindowFrames simulatedFrames) { - if (mScreenDecorWindows.isEmpty()) { - return; - } - - sTmpRect.setEmpty(); - final int displayId = displayFrames.mDisplayId; - - for (int i = mScreenDecorWindows.size() - 1; i >= 0; --i) { - final WindowState w = mScreenDecorWindows.valueAt(i); - if (w.getDisplayId() != displayId || !w.isVisible()) { - // Skip if not on the same display or not visible. - continue; - } - - final boolean isSimulatedLayout = simulatedFrames != null; - if (isSimulatedLayout) { - w.setSimulatedWindowFrames(simulatedFrames); - } - getRotatedWindowBounds(displayFrames, w, sTmpScreenDecorFrame); - final WindowFrames windowFrames = w.getLayoutingWindowFrames(); - windowFrames.setFrames(sTmpScreenDecorFrame /* parentFrame */, - sTmpScreenDecorFrame /* displayFrame */); - try { - w.computeFrame(displayFrames); - } finally { - if (isSimulatedLayout) { - w.setSimulatedWindowFrames(null); - } - } - } - } - private void layoutStatusBar(DisplayFrames displayFrames, Rect simulatedContentFrame) { // decide where the status bar goes ahead of time if (mStatusBar == null) { @@ -1819,8 +1750,7 @@ public class DisplayPolicy { // We've already done the navigation bar, status bar, and all screen decor windows. If the // status bar can receive input, we need to layout it again to accommodate for the IME // window. - if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar - || mScreenDecorWindows.contains(win)) { + if ((win == mStatusBar && !canReceiveInput(win)) || win == mNavigationBar) { return; } final WindowManager.LayoutParams attrs = win.getAttrs(); diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 80b021650c832..d62df85e3cc0c 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -48,6 +48,7 @@ import static android.provider.Settings.Global.DEVELOPMENT_IGNORE_VENDOR_DISPLAY import static android.provider.Settings.Global.DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.INVALID_DISPLAY; +import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; @@ -78,7 +79,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION; import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY; import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER; import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED; -import static android.view.WindowManager.DISPLAY_IME_POLICY_FALLBACK_DISPLAY; import static android.view.WindowManager.TRANSIT_NONE; import static android.view.WindowManager.TRANSIT_RELAUNCH; import static android.view.WindowManagerGlobal.ADD_OKAY; @@ -256,9 +256,9 @@ import android.view.View; import android.view.WindowContentFrameStats; import android.view.WindowInsets; import android.view.WindowManager; +import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManager.LayoutParams; import android.view.WindowManager.RemoveContentMode; -import android.view.WindowManager.DisplayImePolicy; import android.view.WindowManagerGlobal; import android.view.WindowManagerPolicyConstants.PointerEventListener; import android.window.ClientWindowFrames; @@ -1627,7 +1627,7 @@ public class WindowManagerService extends IWindowManager.Stub } final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); - displayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid); + displayPolicy.adjustWindowParamsLw(win, win.mAttrs); win.updateRequestedVisibility(requestedVisibility); res = displayPolicy.validateAddingWindowLw(attrs, callingPid, callingUid); @@ -2197,7 +2197,7 @@ public class WindowManagerService extends IWindowManager.Stub int flagChanges = 0; int privateFlagChanges = 0; if (attrs != null) { - displayPolicy.adjustWindowParamsLw(win, attrs, pid, uid); + displayPolicy.adjustWindowParamsLw(win, attrs); win.mToken.adjustWindowParams(win, attrs); int disableFlags = (attrs.systemUiVisibility | attrs.subtreeSystemUiVisibility) & DISABLE_MASK; diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml index 7f4f3dd588121..0ed037c7e70a9 100644 --- a/services/tests/wmtests/AndroidManifest.xml +++ b/services/tests/wmtests/AndroidManifest.xml @@ -65,8 +65,6 @@ android:turnScreenOn="true" /> - diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java index 21bdc9e7785e0..79b2da1876802 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java @@ -236,8 +236,7 @@ public class DisplayPolicyTests extends WindowTestsBase { final WindowState activity = createBaseApplicationWindow(); activity.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS; - policy.adjustWindowParamsLw(activity, activity.mAttrs, 0 /* callingPid */, - 0 /* callingUid */); + policy.adjustWindowParamsLw(activity, activity.mAttrs); } private WindowState createApplicationWindow() { diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java index 94ffcdab4fa72..20775e84fd8fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java @@ -107,11 +107,9 @@ public class DisplayPolicyTestsBase extends WindowTestsBase { } void addWindow(WindowState win) { - final int callingPid = Binder.getCallingPid(); - final int callingUid = Binder.getCallingUid(); - mDisplayPolicy.adjustWindowParamsLw(win, win.mAttrs, callingPid, callingUid); - assertEquals(WindowManagerGlobal.ADD_OKAY, - mDisplayPolicy.validateAddingWindowLw(win.mAttrs, callingPid, callingUid)); + mDisplayPolicy.adjustWindowParamsLw(win, win.mAttrs); + assertEquals(WindowManagerGlobal.ADD_OKAY, mDisplayPolicy.validateAddingWindowLw( + win.mAttrs, Binder.getCallingPid(), Binder.getCallingUid())); mDisplayPolicy.addWindowLw(win, win.mAttrs); win.mHasSurface = true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java b/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java deleted file mode 100644 index 25ba6db38e053..0000000000000 --- a/services/tests/wmtests/src/com/android/server/wm/ScreenDecorWindowTests.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.wm; - -import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static android.graphics.Color.RED; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; -import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PRESENTATION; -import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.Gravity.BOTTOM; -import static android.view.Gravity.LEFT; -import static android.view.Gravity.RIGHT; -import static android.view.Gravity.TOP; -import static android.view.InsetsState.ITYPE_CLIMATE_BAR; -import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; -import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; -import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; -import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; -import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH; -import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR; -import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; - -import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertEquals; - -import android.app.Activity; -import android.app.ActivityOptions; -import android.app.Instrumentation; -import android.content.Context; -import android.content.Intent; -import android.graphics.PixelFormat; -import android.graphics.Point; -import android.hardware.display.DisplayManager; -import android.hardware.display.VirtualDisplay; -import android.media.ImageReader; -import android.os.Handler; -import android.os.SystemClock; -import android.platform.test.annotations.Presubmit; -import android.util.Pair; -import android.view.Display; -import android.view.DisplayInfo; -import android.view.View; -import android.view.WindowInsets; -import android.view.WindowManager; -import android.widget.TextView; - -import androidx.test.filters.SmallTest; - -import com.android.compatibility.common.util.SystemUtil; - -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import java.util.ArrayList; -import java.util.function.BooleanSupplier; - -/** - * Tests for the {@link android.view.WindowManager.LayoutParams#PRIVATE_FLAG_IS_SCREEN_DECOR} flag. - * - * Build/Install/Run: - * atest WmTests:ScreenDecorWindowTests - */ -// TODO: Add test for FLAG_FULLSCREEN which hides the status bar and also other flags. -// TODO: Test non-Activity windows. -@SmallTest -@Presubmit -public class ScreenDecorWindowTests { - - private final Context mContext = getInstrumentation().getTargetContext(); - private final Instrumentation mInstrumentation = getInstrumentation(); - - private WindowManager mWm; - private ArrayList mWindows = new ArrayList<>(); - - private Activity mTestActivity; - private VirtualDisplay mDisplay; - private ImageReader mImageReader; - - private int mDecorThickness; - private int mHalfDecorThickness; - - @Before - public void setUp() { - final Pair result = createDisplay(); - mDisplay = result.first; - mImageReader = result.second; - final Display display = mDisplay.getDisplay(); - final Context dContext = mContext.createDisplayContext(display); - mWm = dContext.getSystemService(WindowManager.class); - mTestActivity = startActivityOnDisplay(TestActivity.class, display.getDisplayId()); - final Point size = new Point(); - mDisplay.getDisplay().getRealSize(size); - mDecorThickness = Math.min(size.x, size.y) / 3; - mHalfDecorThickness = mDecorThickness / 2; - } - - @After - public void tearDown() { - while (!mWindows.isEmpty()) { - removeWindow(mWindows.get(0)); - } - finishActivity(mTestActivity); - mDisplay.release(); - mImageReader.close(); - } - - @Test - public void testScreenSides() { - // Decor on top - final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - - // Decor at the bottom - updateWindow(decorWindow, BOTTOM, MATCH_PARENT, mDecorThickness, 0, 0); - assertInsetGreaterOrEqual(mTestActivity, BOTTOM, mDecorThickness); - - // Decor to the left - updateWindow(decorWindow, LEFT, mDecorThickness, MATCH_PARENT, 0, 0); - assertInsetGreaterOrEqual(mTestActivity, LEFT, mDecorThickness); - - // Decor to the right - updateWindow(decorWindow, RIGHT, mDecorThickness, MATCH_PARENT, 0, 0); - assertInsetGreaterOrEqual(mTestActivity, RIGHT, mDecorThickness); - } - - // Decor windows (i.e windows using PRIVATE_FLAG_IS_SCREEN_DECOR) are no longer supported. - // PRIVATE_FLAG_IS_SCREEN_DECOR and related code will be deprecated/removed soon. - @Ignore - @Test - public void testMultipleDecors() { - // Test 2 decor windows on-top. - createDecorWindow(TOP, MATCH_PARENT, mHalfDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mHalfDecorThickness); - createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - - // And one at the bottom. - createDecorWindow(BOTTOM, MATCH_PARENT, mHalfDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, BOTTOM, mHalfDecorThickness); - } - - @Test - public void testFlagChange() { - WindowInsets initialInsets = getInsets(mTestActivity); - - final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertTopInsetEquals(mTestActivity, mDecorThickness); - - updateWindow(decorWindow, TOP, MATCH_PARENT, mDecorThickness, - 0, PRIVATE_FLAG_IS_SCREEN_DECOR); - - // TODO: fix test and re-enable assertion. - // initialInsets was not actually immutable and just updated to the current insets, - // meaning this assertion never actually tested anything. Now that WindowInsets actually is - // immutable, it turns out the test was broken. - // assertTopInsetEquals(mTestActivity, initialInsets.getSystemWindowInsetTop()); - - updateWindow(decorWindow, TOP, MATCH_PARENT, mDecorThickness, - PRIVATE_FLAG_IS_SCREEN_DECOR, PRIVATE_FLAG_IS_SCREEN_DECOR); - assertTopInsetEquals(mTestActivity, mDecorThickness); - } - - @Test - public void testRemoval() { - WindowInsets initialInsets = getInsets(mTestActivity); - - final View decorWindow = createDecorWindow(TOP, MATCH_PARENT, mDecorThickness); - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - - removeWindow(decorWindow); - assertTopInsetEquals(mTestActivity, initialInsets.getSystemWindowInsetTop()); - } - - @Test - public void testProvidesInsetsTypes() { - int[] providesInsetsTypes = new int[]{ITYPE_CLIMATE_BAR}; - final View win = createWindow("StatusBarSubPanel", TOP, MATCH_PARENT, mDecorThickness, RED, - FLAG_LAYOUT_IN_SCREEN, 0, providesInsetsTypes); - - assertInsetGreaterOrEqual(mTestActivity, TOP, mDecorThickness); - } - - private View createDecorWindow(int gravity, int width, int height) { - int[] providesInsetsTypes = - new int[]{gravity == TOP ? ITYPE_CLIMATE_BAR : ITYPE_EXTRA_NAVIGATION_BAR}; - return createWindow("decorWindow", gravity, width, height, RED, - FLAG_LAYOUT_IN_SCREEN, PRIVATE_FLAG_IS_SCREEN_DECOR, providesInsetsTypes); - } - - private View createWindow(String name, int gravity, int width, int height, int color, int flags, - int privateFlags, int[] providesInsetsTypes) { - - final View[] viewHolder = new View[1]; - final int finalFlag = flags - | FLAG_NOT_FOCUSABLE | FLAG_WATCH_OUTSIDE_TOUCH | FLAG_NOT_TOUCHABLE; - - // Needs to run on the UI thread. - Handler.getMain().runWithScissors(() -> { - final WindowManager.LayoutParams lp = new WindowManager.LayoutParams( - width, height, TYPE_APPLICATION_OVERLAY, finalFlag, PixelFormat.OPAQUE); - lp.gravity = gravity; - lp.privateFlags |= privateFlags; - lp.providesInsetsTypes = providesInsetsTypes; - - final TextView view = new TextView(mContext); - view.setText("ScreenDecorWindowTests - " + name); - view.setBackgroundColor(color); - mWm.addView(view, lp); - mWindows.add(view); - viewHolder[0] = view; - }, 0); - - waitForIdle(); - return viewHolder[0]; - } - - private void updateWindow(View v, int gravity, int width, int height, - int privateFlags, int privateFlagsMask) { - // Needs to run on the UI thread. - Handler.getMain().runWithScissors(() -> { - final WindowManager.LayoutParams lp = (WindowManager.LayoutParams) v.getLayoutParams(); - lp.gravity = gravity; - lp.width = width; - lp.height = height; - setPrivateFlags(lp, privateFlags, privateFlagsMask); - - mWm.updateViewLayout(v, lp); - }, 0); - - waitForIdle(); - } - - private void removeWindow(View v) { - Handler.getMain().runWithScissors(() -> mWm.removeView(v), 0); - mWindows.remove(v); - waitForIdle(); - } - - private WindowInsets getInsets(Activity a) { - return new WindowInsets(a.getWindow().getDecorView().getRootWindowInsets()); - } - - /** - * Set the flags of the window, as per the - * {@link WindowManager.LayoutParams WindowManager.LayoutParams} - * flags. - * - * @param flags The new window flags (see WindowManager.LayoutParams). - * @param mask Which of the window flag bits to modify. - */ - public void setPrivateFlags(WindowManager.LayoutParams lp, int flags, int mask) { - lp.flags = (lp.flags & ~mask) | (flags & mask); - } - - /** - * Asserts the top inset of {@param activity} is equal to {@param expected} waiting as needed. - */ - private void assertTopInsetEquals(Activity activity, int expected) { - waitForTopInsetEqual(activity, expected); - assertEquals(expected, getInsets(activity).getSystemWindowInsetTop()); - } - - private void waitForTopInsetEqual(Activity activity, int expected) { - waitFor(() -> getInsets(activity).getSystemWindowInsetTop() == expected); - } - - /** - * Asserts the inset at {@param side} of {@param activity} is equal to {@param expected} - * waiting as needed. - */ - private void assertInsetGreaterOrEqual(Activity activity, int side, int expected) { - waitForInsetGreaterOrEqual(activity, side, expected); - - final WindowInsets insets = getInsets(activity); - switch (side) { - case TOP: - assertThat(insets.getSystemWindowInsetTop()).isAtLeast(expected); - break; - case BOTTOM: - assertThat(insets.getSystemWindowInsetBottom()).isAtLeast(expected); - break; - case LEFT: - assertThat(insets.getSystemWindowInsetLeft()).isAtLeast(expected); - break; - case RIGHT: - assertThat(insets.getSystemWindowInsetRight()).isAtLeast(expected); - break; - } - } - - private void waitForInsetGreaterOrEqual(Activity activity, int side, int expected) { - waitFor(() -> { - final WindowInsets insets = getInsets(activity); - switch (side) { - case TOP: return insets.getSystemWindowInsetTop() >= expected; - case BOTTOM: return insets.getSystemWindowInsetBottom() >= expected; - case LEFT: return insets.getSystemWindowInsetLeft() >= expected; - case RIGHT: return insets.getSystemWindowInsetRight() >= expected; - default: return true; - } - }); - } - - private void waitFor(BooleanSupplier waitCondition) { - int retriesLeft = 5; - do { - if (waitCondition.getAsBoolean()) { - break; - } - SystemClock.sleep(500); - } while (retriesLeft-- > 0); - } - - private void finishActivity(Activity a) { - if (a == null) { - return; - } - a.finish(); - waitForIdle(); - } - - private void waitForIdle() { - mInstrumentation.waitForIdleSync(); - } - - private Activity startActivityOnDisplay(Class cls, int displayId) { - final Intent intent = new Intent(mContext, cls); - intent.addFlags(FLAG_ACTIVITY_NEW_TASK); - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchDisplayId(displayId); - - final Activity activity = SystemUtil.runWithShellPermissionIdentity( - () -> mInstrumentation.startActivitySync(intent, options.toBundle()), - "android.permission.ACTIVITY_EMBEDDING"); - waitForIdle(); - - assertEquals(displayId, activity.getDisplayId()); - return activity; - } - - private Pair createDisplay() { - final DisplayManager dm = mContext.getSystemService(DisplayManager.class); - final DisplayInfo displayInfo = new DisplayInfo(); - final Display defaultDisplay = dm.getDisplay(DEFAULT_DISPLAY); - defaultDisplay.getDisplayInfo(displayInfo); - final String name = "ScreenDecorWindowTests"; - int flags = VIRTUAL_DISPLAY_FLAG_PRESENTATION | VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY; - - final ImageReader imageReader = ImageReader.newInstance( - displayInfo.logicalWidth, displayInfo.logicalHeight, PixelFormat.RGBA_8888, 2); - - final VirtualDisplay display = dm.createVirtualDisplay(name, displayInfo.logicalWidth, - displayInfo.logicalHeight, displayInfo.logicalDensityDpi, imageReader.getSurface(), - flags); - - return Pair.create(display, imageReader); - } - - public static class TestActivity extends Activity { - } -}