Merge "Fix ANR when switching the app task but IME selection dialog focused" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
1181f3e9aa
@@ -116,8 +116,10 @@ public abstract class InputMethodManagerInternal {
|
||||
*
|
||||
* @param windowToken the window token that is now in control, or {@code null} if no client
|
||||
* window is in control of the IME.
|
||||
* @param imeParentChanged {@code true} when the window manager thoughts the IME surface parent
|
||||
* will end up to change later, or {@code false} otherwise.
|
||||
*/
|
||||
public abstract void reportImeControl(@Nullable IBinder windowToken);
|
||||
public abstract void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged);
|
||||
|
||||
/**
|
||||
* Destroys the IME surface.
|
||||
@@ -176,7 +178,8 @@ public abstract class InputMethodManagerInternal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportImeControl(@Nullable IBinder windowToken) {
|
||||
public void reportImeControl(@Nullable IBinder windowToken,
|
||||
boolean imeParentChanged) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4937,13 +4937,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
return mInputManagerInternal.transferTouchFocus(sourceInputToken, curHostInputToken);
|
||||
}
|
||||
|
||||
private void reportImeControl(@Nullable IBinder windowToken) {
|
||||
private void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) {
|
||||
synchronized (mMethodMap) {
|
||||
if (mCurFocusedWindow != windowToken) {
|
||||
// mCurPerceptible was set by the focused window, but it is no longer in control,
|
||||
// so we reset mCurPerceptible.
|
||||
mCurPerceptible = true;
|
||||
}
|
||||
if (imeParentChanged) {
|
||||
// Hide the IME method menu earlier when the IME surface parent will change in
|
||||
// case seeing the dialog dismiss flickering during the next focused window
|
||||
// starting the input connection.
|
||||
mMenuController.hideInputMethodMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5001,8 +5007,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportImeControl(@Nullable IBinder windowToken) {
|
||||
mService.reportImeControl(windowToken);
|
||||
public void reportImeControl(@Nullable IBinder windowToken, boolean imeParentChanged) {
|
||||
mService.reportImeControl(windowToken, imeParentChanged);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -225,7 +225,8 @@ public final class MultiClientInputMethodManagerService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reportImeControl(@Nullable IBinder windowToken) {
|
||||
public void reportImeControl(@Nullable IBinder windowToken,
|
||||
boolean imeParentChanged) {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -729,12 +729,19 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
|
||||
// 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
|
||||
// However, in case IME created a child window or the IME selection dialog 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 && (mImeLayeringTarget == null
|
||||
|| !mImeLayeringTarget.getRequestedVisibility(ITYPE_IME))) {
|
||||
return false;
|
||||
if (w.mAttrs.type == TYPE_INPUT_METHOD_DIALOG) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (w.isChildWindow()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final ActivityRecord activity = w.mActivityRecord;
|
||||
@@ -3978,7 +3985,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
// Update Ime parent when IME insets leash created or the new IME layering target might
|
||||
// updated from setImeLayeringTarget, which is the best time that default IME visibility
|
||||
// has been settled down after IME control target changed.
|
||||
if (prevImeControlTarget != mImeControlTarget || forceUpdateImeParent) {
|
||||
final boolean imeParentChanged =
|
||||
prevImeControlTarget != mImeControlTarget || forceUpdateImeParent;
|
||||
if (imeParentChanged) {
|
||||
updateImeParent();
|
||||
}
|
||||
|
||||
@@ -3986,7 +3995,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
||||
final IBinder token = win != null ? win.mClient.asBinder() : null;
|
||||
// Note: not allowed to call into IMMS with the WM lock held, hence the post.
|
||||
mWmService.mH.post(() ->
|
||||
InputMethodManagerInternal.get().reportImeControl(token)
|
||||
InputMethodManagerInternal.get().reportImeControl(token, imeParentChanged)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_SCREENSHOT;
|
||||
@@ -2201,6 +2202,31 @@ public class DisplayContentTests extends WindowTestsBase {
|
||||
assertNotEquals(imeChildWindow, mDisplayContent.findFocusedWindow());
|
||||
}
|
||||
|
||||
@UseTestDisplay(addWindows = W_INPUT_METHOD)
|
||||
@Test
|
||||
public void testImeMenuDialogFocusWhenImeLayeringTargetChanges() {
|
||||
final WindowState imeMenuDialog =
|
||||
createWindow(mImeWindow, TYPE_INPUT_METHOD_DIALOG, "imeMenuDialog");
|
||||
makeWindowVisibleAndDrawn(imeMenuDialog, mImeWindow);
|
||||
assertTrue(imeMenuDialog.canReceiveKeys());
|
||||
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
|
||||
|
||||
// Verify imeMenuDialog 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(imeMenuDialog, mDisplayContent.findFocusedWindow());
|
||||
|
||||
// Verify imeMenuDialog 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(imeMenuDialog, mDisplayContent.findFocusedWindow());
|
||||
}
|
||||
|
||||
private void removeRootTaskTests(Runnable runnable) {
|
||||
final TaskDisplayArea taskDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
|
||||
final Task rootTask1 = taskDisplayArea.createRootTask(WINDOWING_MODE_FULLSCREEN,
|
||||
|
||||
Reference in New Issue
Block a user