Don't give the IME child window focus when switching tasks

When switching the app task, we keep the IME window visibility for
better transitioning experiences.

However, in case IME created a child window without dismissing
during the task switching to keep the window focus because the IME
window has higher window hierarchy.

Hence, we don't give it focus if the next IME layering target
doesn't actually request the IME visible.

Fix: 186329504
Test: manual as issue steps:
  1) Tap any text box to bring up Gboard.
  2) Tap access point -> '..' -> Share Gboard or Quality Bug Report.
  3) Swipe up to Home screen.
  4) Tap another text box.
  6) Verify if the IME can shown as expected after editor focused
Test: atest DisplayContentTests#\
      testImeChildWindowFocusWhenImeLayeringTargetChanges
Change-Id: I72618745542f33bcbb1001bd3b812e79f7652dda
This commit is contained in:
Ming-Shin Lu
2021-05-12 20:48:44 +08:00
parent 63a1453832
commit f4c200f56c
2 changed files with 36 additions and 0 deletions

View File

@@ -724,6 +724,16 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
return false;
}
// When switching the app task, we keep the IME window visibility for better
// transitioning experiences.
// However, in case IME created a child window without dismissing during the task
// switching to keep the window focus because IME window has higher window hierarchy,
// we don't give it focus if the next IME layering target doesn't request IME visible.
if (w.mIsImWindow && w.isChildWindow() && (mImeLayeringTarget == null
|| !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME))) {
return false;
}
final ActivityRecord activity = w.mActivityRecord;
if (focusedApp == null) {

View File

@@ -31,6 +31,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_PRIVATE;
import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
import static android.view.DisplayCutout.fromBoundingRect;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
@@ -2136,6 +2137,31 @@ public class DisplayContentTests extends WindowTestsBase {
ACTIVITY_TYPE_STANDARD));
}
@UseTestDisplay(addWindows = W_INPUT_METHOD)
@Test
public void testImeChildWindowFocusWhenImeLayeringTargetChanges() {
final WindowState imeChildWindow =
createWindow(mImeWindow, TYPE_APPLICATION_ATTACHED_DIALOG, "imeChildWindow");
makeWindowVisibleAndDrawn(imeChildWindow, mImeWindow);
assertTrue(imeChildWindow.canReceiveKeys());
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
// Verify imeChildWindow can be focused window if the next IME target requests IME visible.
final WindowState imeAppTarget =
createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "imeAppTarget");
mDisplayContent.setImeLayeringTarget(imeAppTarget);
spyOn(imeAppTarget);
doReturn(true).when(imeAppTarget).getRequestedVisibility(ITYPE_IME);
assertEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
// Verify imeChildWindow doesn't be focused window if the next IME target does not
// request IME visible.
final WindowState nextImeAppTarget =
createWindow(null, TYPE_BASE_APPLICATION, mDisplayContent, "nextImeAppTarget");
mDisplayContent.setImeLayeringTarget(nextImeAppTarget);
assertNotEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
}
private void removeRootTaskTests(Runnable runnable) {
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,