Set IME insets invisible if the target is above IME

We would remove the insets source of IME before dispatching to the
target above IME previously. However, when the z-order of an invisible
IME is changed, the client may receive unnecessary insets-change
callcacks (InsetsState with or without IME source).

With this CL, as long as IME is invisible, no matter what z-order the
IME has, the client will get the same IME source.

Fix: 152722388
Test: atest ChildlessActivityTest InsetsStateControllerTest
Change-Id: I9f147976be47a9fced4493dba10113b8ab048f4e
This commit is contained in:
Tiger Huang
2020-04-15 05:25:16 +08:00
parent 82dc6147f1
commit a70fd87903
2 changed files with 35 additions and 30 deletions

View File

@@ -171,7 +171,7 @@ class InsetsStateController {
if (aboveIme) {
state = new InsetsState(state);
state.removeSource(ITYPE_IME);
state.setSourceVisible(ITYPE_IME, false);
}
return state;

View File

@@ -29,9 +29,11 @@ import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.spy;
@@ -44,7 +46,6 @@ import android.view.InsetsSourceControl;
import android.view.InsetsState;
import android.view.test.InsetsModeSession;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import org.junit.AfterClass;
@@ -153,22 +154,24 @@ public class InsetsStateControllerTest extends WindowTestsBase {
@Test
public void testStripForDispatch_belowIme() {
getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
app.mBehindIme = true;
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
assertNotNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
}
@Test
public void testStripForDispatch_aboveIme() {
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
app.mBehindIme = false;
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
}
@Test
@@ -191,8 +194,9 @@ public class InsetsStateControllerTest extends WindowTestsBase {
mDisplayContent.setLayoutNeeded();
mDisplayContent.applySurfaceChangesTransaction();
// app won't get IME insets while above IME.
assertNull(getController().getInsetsForDispatch(app).peekSource(ITYPE_IME));
// app won't get visible IME insets while above IME even when IME is visible.
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
assertFalse(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
// Reset invocation counter.
clearInvocations(app);
@@ -206,43 +210,44 @@ public class InsetsStateControllerTest extends WindowTestsBase {
// 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));
// app will get visible IME insets while below IME when IME is visible.
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
}
@Test
public void testStripForDispatch_childWindow_altFocusable() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
child.mAttrs.flags |= FLAG_ALT_FOCUSABLE_IM;
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
mDisplayContent.computeImeTarget(true);
mDisplayContent.setLayoutNeeded();
mDisplayContent.applySurfaceChangesTransaction();
// IME cannot be the IME target.
ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
assertNull(getController().getInsetsForDispatch(child).peekSource(ITYPE_IME));
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
assertFalse(getController().getInsetsForDispatch(child).getSource(ITYPE_IME).isVisible());
}
@Test
public void testStripForDispatch_childWindow_splitScreen() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
getController().getSourceProvider(ITYPE_IME).setWindow(mImeWindow, null, null);
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
final WindowState child = createWindow(app, TYPE_APPLICATION, "child");
child.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
child.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
final WindowState ime = createWindow(null, TYPE_APPLICATION, "ime");
mDisplayContent.computeImeTarget(true);
mDisplayContent.setLayoutNeeded();
mDisplayContent.applySurfaceChangesTransaction();
// IME cannot be the IME target.
ime.mAttrs.flags |= FLAG_NOT_FOCUSABLE;
getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
assertNull(getController().getInsetsForDispatch(child).peekSource(ITYPE_IME));
getController().getRawInsetsState().setSourceVisible(ITYPE_IME, true);
assertTrue(getController().getInsetsForDispatch(app).getSource(ITYPE_IME).isVisible());
assertFalse(getController().getInsetsForDispatch(child).getSource(ITYPE_IME).isVisible());
}
@Test