summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tiger Huang <tigerhuang@google.com> 2023-12-08 07:07:27 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-12-08 07:07:27 +0000
commit43a268fbfdc6d025451c32b51b8fbadfdead3d4e (patch)
treedb71e926f69afa180cf47f23362c22157f2a6772
parentbdd1caebf987f636339aa7992cb328b8c333493f (diff)
parentf6f102cc8d209eafce40e4749fbf031cb568ee8f (diff)
Merge "Add PRIVATE_FLAG_CONSUME_IME_INSETS" into main
-rw-r--r--core/java/android/view/WindowManager.java14
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java16
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java53
5 files changed, 117 insertions, 9 deletions
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 046ea77f196d..8a37c7c1ef09 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -3251,6 +3251,13 @@ public interface WindowManager extends ViewManager {
public static final int PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC = 1 << 24;
/**
+ * Flag to indicate that the window consumes the insets of {@link Type#ime()}. This makes
+ * windows below this window unable to receive visible IME insets.
+ * @hide
+ */
+ public static final int PRIVATE_FLAG_CONSUME_IME_INSETS = 1 << 25;
+
+ /**
* Flag to indicate that the window is controlling the appearance of system bars. So we
* don't need to adjust it by reading its system UI flags for compatibility.
* @hide
@@ -3334,6 +3341,7 @@ public interface WindowManager extends ViewManager {
PRIVATE_FLAG_EXCLUDE_FROM_SCREEN_MAGNIFICATION,
PRIVATE_FLAG_NOT_MAGNIFIABLE,
PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
+ PRIVATE_FLAG_CONSUME_IME_INSETS,
PRIVATE_FLAG_APPEARANCE_CONTROLLED,
PRIVATE_FLAG_BEHAVIOR_CONTROLLED,
PRIVATE_FLAG_FIT_INSETS_CONTROLLED,
@@ -3432,6 +3440,10 @@ public interface WindowManager extends ViewManager {
equals = PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC,
name = "COLOR_SPACE_AGNOSTIC"),
@ViewDebug.FlagToString(
+ mask = PRIVATE_FLAG_CONSUME_IME_INSETS,
+ equals = PRIVATE_FLAG_CONSUME_IME_INSETS,
+ name = "CONSUME_IME_INSETS"),
+ @ViewDebug.FlagToString(
mask = PRIVATE_FLAG_APPEARANCE_CONTROLLED,
equals = PRIVATE_FLAG_APPEARANCE_CONTROLLED,
name = "APPEARANCE_CONTROLLED"),
@@ -3458,7 +3470,7 @@ public interface WindowManager extends ViewManager {
@ViewDebug.FlagToString(
mask = PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY,
equals = PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY,
- name = "PRIVATE_FLAG_SYSTEM_APPLICATION_OVERLAY")
+ name = "SYSTEM_APPLICATION_OVERLAY")
})
@PrivateFlags
@TestApi
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index b862d7c28b52..460a68f48ff6 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -39,6 +39,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCRE
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_CONSUME_IME_INSETS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IMMERSIVE_CONFIRMATION_WINDOW;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INTERCEPT_GLOBAL_DRAG_AND_DROP;
@@ -272,6 +273,8 @@ public class DisplayPolicy {
private @InsetsType int mForciblyShownTypes;
+ private boolean mImeInsetsConsumed;
+
private boolean mIsImmersiveMode;
// The windows we were told about in focusChanged.
@@ -1420,6 +1423,7 @@ public class DisplayPolicy {
mShowingDream = false;
mIsFreeformWindowOverlappingWithNavBar = false;
mForciblyShownTypes = 0;
+ mImeInsetsConsumed = false;
}
/**
@@ -1481,6 +1485,17 @@ public class DisplayPolicy {
mForciblyShownTypes |= win.mAttrs.forciblyShownTypes;
}
+ if (win.mImeInsetsConsumed != mImeInsetsConsumed) {
+ win.mImeInsetsConsumed = mImeInsetsConsumed;
+ final WindowState imeWin = mDisplayContent.mInputMethodWindow;
+ if (win.isReadyToDispatchInsetsState() && imeWin != null && imeWin.isVisible()) {
+ win.notifyInsetsChanged();
+ }
+ }
+ if ((attrs.privateFlags & PRIVATE_FLAG_CONSUME_IME_INSETS) != 0 && win.isVisible()) {
+ mImeInsetsConsumed = true;
+ }
+
if (!affectsSystemUi) {
return;
}
@@ -2828,6 +2843,7 @@ public class DisplayPolicy {
}
}
pw.print(prefix); pw.print("mTopIsFullscreen="); pw.println(mTopIsFullscreen);
+ pw.print(prefix); pw.print("mImeInsetsConsumed="); pw.println(mImeInsetsConsumed);
pw.print(prefix); pw.print("mForceShowNavigationBarEnabled=");
pw.print(mForceShowNavigationBarEnabled);
pw.print(" mAllowLockscreenWhenOn="); pw.println(mAllowLockscreenWhenOn);
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index c089d107d07d..781567990235 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -391,13 +391,26 @@ class InsetsPolicy {
if (originalImeSource != null) {
final boolean imeVisibility = w.isRequestedVisible(Type.ime());
- final InsetsState state = copyState ? new InsetsState(originalState)
+ final InsetsState state = copyState
+ ? new InsetsState(originalState)
: originalState;
final InsetsSource imeSource = new InsetsSource(originalImeSource);
imeSource.setVisible(imeVisibility);
state.addSource(imeSource);
return state;
}
+ } else if (w.mImeInsetsConsumed) {
+ // Set the IME source (if there is one) to be invisible if it has been consumed.
+ final InsetsSource originalImeSource = originalState.peekSource(ID_IME);
+ if (originalImeSource != null && originalImeSource.isVisible()) {
+ final InsetsState state = copyState
+ ? new InsetsState(originalState)
+ : originalState;
+ final InsetsSource imeSource = new InsetsSource(originalImeSource);
+ imeSource.setVisible(false);
+ state.addSource(imeSource);
+ return state;
+ }
}
return originalState;
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index b890a9e9bd04..c7a7e28cc5eb 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -668,6 +668,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
boolean mSeamlesslyRotated = false;
/**
+ * Whether the IME insets have been consumed. If {@code true}, this window won't be able to
+ * receive visible IME insets; {@code false}, otherwise.
+ */
+ boolean mImeInsetsConsumed = false;
+
+ /**
* The insets state of sources provided by windows above the current window.
*/
final InsetsState mAboveInsetsState = new InsetsState();
@@ -1487,7 +1493,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (insetsChanged) {
mWindowFrames.setInsetsChanged(false);
- mWmService.mWindowsInsetsChanged--;
+ if (mWmService.mWindowsInsetsChanged > 0) {
+ mWmService.mWindowsInsetsChanged--;
+ }
if (mWmService.mWindowsInsetsChanged == 0) {
mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED);
}
@@ -3796,13 +3804,15 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
void notifyInsetsChanged() {
ProtoLog.d(WM_DEBUG_WINDOW_INSETS, "notifyInsetsChanged for %s ", this);
- mWindowFrames.setInsetsChanged(true);
+ if (!mWindowFrames.hasInsetsChanged()) {
+ mWindowFrames.setInsetsChanged(true);
- // If the new InsetsState won't be dispatched before releasing WM lock, the following
- // message will be executed.
- mWmService.mWindowsInsetsChanged++;
- mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED);
- mWmService.mH.sendEmptyMessage(WindowManagerService.H.INSETS_CHANGED);
+ // If the new InsetsState won't be dispatched before releasing WM lock, the following
+ // message will be executed.
+ mWmService.mWindowsInsetsChanged++;
+ mWmService.mH.removeMessages(WindowManagerService.H.INSETS_CHANGED);
+ mWmService.mH.sendEmptyMessage(WindowManagerService.H.INSETS_CHANGED);
+ }
final WindowContainer p = getParent();
if (p != null) {
@@ -4192,6 +4202,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
} else {
pw.print("null");
}
+ pw.println();
if (mXOffset != 0 || mYOffset != 0) {
pw.println(prefix + "mXOffset=" + mXOffset + " mYOffset=" + mYOffset);
@@ -4225,6 +4236,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
if (computeDragResizing()) {
pw.println(prefix + "computeDragResizing=" + computeDragResizing());
}
+ if (mImeInsetsConsumed) {
+ pw.println(prefix + "mImeInsetsConsumed=true");
+ }
pw.println(prefix + "isOnScreen=" + isOnScreen());
pw.println(prefix + "isVisible=" + isVisible());
pw.println(prefix + "keepClearAreas: restricted=" + mKeepClearAreas
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
index ffa1ed926766..38a66a9d5486 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java
@@ -19,10 +19,13 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.view.InsetsSource.ID_IME;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
+import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsets.Type.statusBars;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_CONSUME_IME_INSETS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
@@ -432,6 +435,56 @@ public class InsetsPolicyTest extends WindowTestsBase {
}
+ @SetupWindows(addWindows = W_INPUT_METHOD)
+ @Test
+ public void testConsumeImeInsets() {
+ final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+ final InsetsSource imeSource = new InsetsSource(ID_IME, ime());
+ imeSource.setVisible(true);
+ mImeWindow.mHasSurface = true;
+
+ final WindowState win1 = addWindow(TYPE_APPLICATION, "win1");
+ final WindowState win2 = addWindow(TYPE_APPLICATION, "win2");
+
+ win1.mAboveInsetsState.addSource(imeSource);
+ win1.mHasSurface = true;
+ win2.mAboveInsetsState.addSource(imeSource);
+ win2.mHasSurface = true;
+
+ assertTrue(mImeWindow.isVisible());
+ assertTrue(win1.isVisible());
+ assertTrue(win2.isVisible());
+
+ // Make sure both windows have visible IME insets.
+ assertTrue(win1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+ assertTrue(win2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+
+ win2.mAttrs.privateFlags |= PRIVATE_FLAG_CONSUME_IME_INSETS;
+
+ displayPolicy.beginPostLayoutPolicyLw();
+ displayPolicy.applyPostLayoutPolicyLw(win2, win2.mAttrs, null, null);
+ displayPolicy.applyPostLayoutPolicyLw(win1, win1.mAttrs, null, null);
+ displayPolicy.finishPostLayoutPolicyLw();
+
+ // Make sure win2 doesn't have visible IME insets, but win1 still does.
+ assertTrue(win2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+ assertFalse(win1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+ assertTrue(win1.getWindowFrames().hasInsetsChanged());
+
+ win2.mAttrs.privateFlags &= ~PRIVATE_FLAG_CONSUME_IME_INSETS;
+ win2.getWindowFrames().setInsetsChanged(false);
+
+ displayPolicy.beginPostLayoutPolicyLw();
+ displayPolicy.applyPostLayoutPolicyLw(win2, win2.mAttrs, null, null);
+ displayPolicy.applyPostLayoutPolicyLw(win1, win1.mAttrs, null, null);
+ displayPolicy.finishPostLayoutPolicyLw();
+
+ // Make sure both windows have visible IME insets.
+ assertTrue(win1.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+ assertTrue(win2.getInsetsState().isSourceOrDefaultVisible(ID_IME, ime()));
+ assertTrue(win1.getWindowFrames().hasInsetsChanged());
+ }
+
private WindowState addNavigationBar() {
final Binder owner = new Binder();
final WindowState win = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");