summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java8
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java43
3 files changed, 59 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 01081404a502..ce7e79714c39 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -503,6 +503,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
/** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
+ /** Windows whose client's insets states are not up-to-date. */
+ final ArrayList<WindowState> mWinInsetsChanged = new ArrayList<>();
+
private ScreenRotationAnimation mScreenRotationAnimation;
/**
@@ -708,7 +711,10 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
}
// Sets mBehindIme for each window. Windows behind IME can get IME insets.
- w.mBehindIme = mTmpWindowsBehindIme;
+ if (w.mBehindIme != mTmpWindowsBehindIme) {
+ w.mBehindIme = mTmpWindowsBehindIme;
+ mWinInsetsChanged.add(w);
+ }
if (w == mInputMethodWindow) {
mTmpWindowsBehindIme = true;
}
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 04454a5b33ec..ba14d48d38ea 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -227,10 +227,19 @@ class InsetsStateController {
for (int i = mProviders.size() - 1; i >= 0; i--) {
mProviders.valueAt(i).onPostLayout();
}
+ final ArrayList<WindowState> winInsetsChanged = mDisplayContent.mWinInsetsChanged;
if (!mLastState.equals(mState)) {
mLastState.set(mState, true /* copySources */);
notifyInsetsChanged();
+ } else {
+ // The global insets state has not changed but there might be windows whose conditions
+ // (e.g., z-order) have changed. They can affect the insets states that we dispatch to
+ // the clients.
+ for (int i = winInsetsChanged.size() - 1; i >= 0; i--) {
+ winInsetsChanged.get(i).notifyInsetsChanged();
+ }
}
+ winInsetsChanged.clear();
}
void onInsetsModified(InsetsControlTarget windowState, InsetsState state) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index db7bce4c8753..17ebe4f67377 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -32,6 +32,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
@@ -169,6 +173,45 @@ public class InsetsStateControllerTest extends WindowTestsBase {
}
@Test
+ public void testStripForDispatch_imeOrderChanged() {
+ getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
+
+ // This window can be the IME target while app cannot be the IME target.
+ createWindow(null, TYPE_APPLICATION, "base");
+
+ // Send our spy window (app) into the system so that we can detect the invocation.
+ final WindowState win = createWindow(null, TYPE_APPLICATION, "app");
+ final WindowToken parent = win.mToken;
+ parent.removeChild(win);
+ final WindowState app = spy(win);
+ parent.addWindow(app);
+
+ // Adding FLAG_NOT_FOCUSABLE makes app above IME.
+ app.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
+ mDisplayContent.computeImeTarget(true);
+ mDisplayContent.setLayoutNeeded();
+ mDisplayContent.applySurfaceChangesTransaction();
+
+ // app won't get IME insets while above IME.
+ assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
+
+ // Reset invocation counter.
+ clearInvocations(app);
+
+ // Removing FLAG_NOT_FOCUSABLE makes app below IME.
+ app.mAttrs.flags &= ~FLAG_NOT_FOCUSABLE;
+ mDisplayContent.computeImeTarget(true);
+ mDisplayContent.setLayoutNeeded();
+ mDisplayContent.applySurfaceChangesTransaction();
+
+ // Make sure app got notified.
+ verify(app, atLeast(1)).notifyInsetsChanged();
+
+ // app will get IME insets while below IME.
+ assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
+ }
+
+ @Test
public void testStripForDispatch_childWindow_altFocusable() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");