diff options
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"); |