Update insets state for each window if its mBehindIme is changed
InsetsStateController would dispatch a different insets state to a window accroding to its condition. For example, a window behind IME can get the insets state different from one got from a window above IME. So when the conditions change, we should update the insets state to the client. Fix: 152839133 Test: atest InsetsStateControllerTest Change-Id: I7a846d55da92a652d79fb81dfd79abcc87971830
This commit is contained in:
@@ -504,6 +504,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;
|
||||
|
||||
/**
|
||||
@@ -722,7 +725,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;
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
@@ -168,6 +172,45 @@ public class InsetsStateControllerTest extends WindowTestsBase {
|
||||
assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Reference in New Issue
Block a user