summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ming-Shin Lu <lumark@google.com> 2020-04-30 22:20:10 +0800
committer Ming-Shin Lu <lumark@google.com> 2020-05-09 00:36:27 +0800
commita4cb6f3a45643102b1b494b7f4945bbc85c28629 (patch)
tree1e31d14b25cfe196c269112e9f9ae70e61198bfc
parent672ebfc2920eefc17c24b3678afb59ee4303c8a0 (diff)
Fix focus cleared and password keyboard shown during IME switching
When IME switches, InputMethodService will be rebound and re-initialize input view, since it needs take time to update the layout, if the insets calculation happens during the layout, the givenContentInsets are not ready yet during this phases, then the insets size will abnormal and may cause the IME target layout will be resized to zero height after applied insets change. If the view layout is focused, system will clear such 0-sized view focus, since user can't easily aware and it's not safe to focus on invisible view (refer CL[1]), then after IME switches, input connection will break because the view focus lost. Make sure to set the valid IME insets sources frame when the server side visible set as true in InsetSourceProvider. [1]: 5db64eb1da42118af65ceba1d0612fd82c294608 Fix: 153612876 Test: atest InsetsSourceProviderTest#testUpdateSourceFrameForIme Test: atest InsetsSourceTest InsetsStateTest InsetsSourceProviderTest \ InsetsControllerTest InsetsStateControllerTest \ InsetsSourceConsumerTest Test: atest ImeInsetsControllerTest Change-Id: Id2c482e112c1d73cf7d5b3ba5e1a2d5775f47298
-rw-r--r--services/core/java/com/android/server/wm/InsetsSourceProvider.java15
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java31
2 files changed, 42 insertions, 4 deletions
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 56986c2e7e41..dfd44f549c49 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -166,11 +166,18 @@ class InsetsSourceProvider {
return;
}
- mTmpRect.set(mWin.getFrameLw());
- if (mFrameProvider != null) {
- mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
+ // Make sure we set the valid source frame only when server visible is true, because the
+ // frame may not yet determined that server side doesn't think the window is ready to
+ // visible. (i.e. No surface, pending insets that were given during layout, etc..)
+ if (mServerVisible) {
+ mTmpRect.set(mWin.getFrameLw());
+ if (mFrameProvider != null) {
+ mFrameProvider.accept(mWin.getDisplayContent().mDisplayFrames, mWin, mTmpRect);
+ } else {
+ mTmpRect.inset(mWin.mGivenContentInsets);
+ }
} else {
- mTmpRect.inset(mWin.mGivenContentInsets);
+ mTmpRect.setEmpty();
}
mSource.setFrame(mTmpRect);
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
index ca016761438b..9bf9ffed57be 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsSourceProviderTest.java
@@ -16,8 +16,10 @@
package com.android.server.wm;
+import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -44,12 +46,17 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
private InsetsSource mSource = new InsetsSource(ITYPE_STATUS_BAR);
private InsetsSourceProvider mProvider;
+ private InsetsSource mImeSource = new InsetsSource(ITYPE_IME);
+ private InsetsSourceProvider mImeProvider;
@Before
public void setUp() throws Exception {
mSource.setVisible(true);
mProvider = new InsetsSourceProvider(mSource,
mDisplayContent.getInsetsStateController(), mDisplayContent);
+ mProvider.setServerVisible(true);
+ mImeProvider = new InsetsSourceProvider(mImeSource,
+ mDisplayContent.getInsetsStateController(), mDisplayContent);
}
@Test
@@ -166,6 +173,30 @@ public class InsetsSourceProviderTest extends WindowTestsBase {
}
@Test
+ public void testUpdateSourceFrameForIme() {
+ final WindowState inputMethod = createWindow(null, TYPE_INPUT_METHOD, "inputMethod");
+
+ inputMethod.getFrameLw().set(new Rect(0, 400, 500, 500));
+
+ mImeProvider.setWindow(inputMethod, null, null);
+ mImeProvider.setServerVisible(false);
+ mImeSource.setVisible(true);
+ mImeProvider.updateSourceFrame();
+ assertEquals(new Rect(0, 0, 0, 0), mImeSource.getFrame());
+ Insets insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 0, 0), insets);
+
+ mImeProvider.setServerVisible(true);
+ mImeSource.setVisible(true);
+ mImeProvider.updateSourceFrame();
+ assertEquals(inputMethod.getFrameLw(), mImeSource.getFrame());
+ insets = mImeSource.calculateInsets(new Rect(0, 0, 500, 500),
+ false /* ignoreVisibility */);
+ assertEquals(Insets.of(0, 0, 0, 100), insets);
+ }
+
+ @Test
public void testInsetsModified() {
final WindowState statusBar = createWindow(null, TYPE_APPLICATION, "statusBar");
final WindowState target = createWindow(null, TYPE_APPLICATION, "target");