[DO NOT MERGE] DisplayImeController: fix out-of-sync IME visibility

This change is based on CL[1] in rvc-qpr-dev code base.

Note: This cherry-picked change isn't completely same as master one,
it add a method "getImeRequestedVisibility" in InsetsControlTarget
since "getRequestedVisibility" didn't exist in rvc-qpr currently.

Fixes an issue where the DisplayImeController would disagree with
the InputMethodManagerService about the visibility of the IME.

Currently, the Insets component is supposed to execute the
visibility as dictated by IMMS; however, when the DisplayImeController
became the control target, previously it would just apply the IME
visibility that was last requested of it - regardless of the
changes to it that may have happened while it was not the control
target.

Eventually, IME visibility should be driven by the requested IME
inset visibility of the focused window, instead of the separate
dispatch we have now from IMMS.

[1]:I1f140af6bcccbcbe6efb2fde9a789ac4c7bd127f

Bug: 167780081
Test: atest ImeInsetsSourceProviderTest
Change-Id: I3962f3aa26d9325d7d8a4611f13a637d46337fef
This commit is contained in:
Wilson Wu
2020-12-17 21:13:31 +08:00
parent 0d094ad38e
commit f03366ee16
8 changed files with 70 additions and 4 deletions

View File

@@ -203,6 +203,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged
return;
}
mImeShowing = insetsState.getSourceOrDefaultVisibility(InsetsState.ITYPE_IME);
final InsetsSource newSource = insetsState.getSource(InsetsState.ITYPE_IME);
final Rect newFrame = newSource.getFrame();
final Rect oldFrame = mInsetsState.getSource(InsetsState.ITYPE_IME).getFrame();

View File

@@ -5877,6 +5877,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
Slog.w(TAG, "Failed to deliver showInsets", e);
}
}
@Override
public boolean getImeRequestedVisibility(@InternalInsetsType int type) {
return getInsetsStateController().getImeSourceProvider().isImeShowing();
}
}
/**

View File

@@ -35,6 +35,7 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
private InsetsControlTarget mImeTargetFromIme;
private Runnable mShowImeRunner;
private boolean mIsImeLayoutDrawn;
private boolean mImeShowing;
ImeInsetsSourceProvider(InsetsSource source,
InsetsStateController stateController, DisplayContent displayContent) {
@@ -74,6 +75,7 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
ProtoLog.i(WM_DEBUG_IME, "call showInsets(ime) on %s",
target.getWindow() != null ? target.getWindow().getName() : "");
setImeShowing(true);
target.showInsets(WindowInsets.Type.ime(), true /* fromIme */);
if (target != mImeTargetFromIme && mImeTargetFromIme != null) {
ProtoLog.w(WM_DEBUG_IME,
@@ -147,11 +149,29 @@ class ImeInsetsSourceProvider extends InsetsSourceProvider {
@Override
public void dump(PrintWriter pw, String prefix) {
super.dump(pw, prefix);
pw.print(prefix);
pw.print("mImeShowing=");
pw.print(mImeShowing);
if (mImeTargetFromIme != null) {
pw.print(prefix);
pw.print("showImePostLayout pending for mImeTargetFromIme=");
pw.print(" showImePostLayout pending for mImeTargetFromIme=");
pw.print(mImeTargetFromIme);
pw.println();
}
pw.println();
}
/**
* Sets whether the IME is currently supposed to be showing according to
* InputMethodManagerService.
*/
public void setImeShowing(boolean imeShowing) {
mImeShowing = imeShowing;
}
/**
* Returns whether the IME is currently supposed to be showing according to
* InputMethodManagerService.
*/
public boolean isImeShowing() {
return mImeShowing;
}
}

View File

@@ -38,6 +38,13 @@ interface InsetsControlTarget {
return null;
}
/**
* @return The requested visibility of this target.
*/
default boolean getImeRequestedVisibility(@InsetsState.InternalInsetsType int type) {
return InsetsState.getDefaultVisibility(type);
}
/**
* @return The requested {@link InsetsState} of this target.
*/

View File

@@ -279,7 +279,7 @@ class InsetsSourceProvider {
}
mAdapter = new ControlAdapter();
if (getSource().getType() == ITYPE_IME) {
setClientVisible(InsetsState.getDefaultVisibility(mSource.getType()));
setClientVisible(target.getImeRequestedVisibility(mSource.getType()));
}
final Transaction t = mDisplayContent.getPendingTransaction();
mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */,

View File

@@ -7637,6 +7637,9 @@ public class WindowManagerService extends IWindowManager.Stub
dc.mInputMethodControlTarget.hideInsets(
WindowInsets.Type.ime(), true /* fromIme */);
}
if (dc != null) {
dc.getInsetsStateController().getImeSourceProvider().setImeShowing(false);
}
}
}

View File

@@ -18,7 +18,9 @@ package com.android.server.wm;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.graphics.PixelFormat;
@@ -64,4 +66,22 @@ public class ImeInsetsSourceProviderTest extends WindowTestsBase {
mImeProvider.scheduleShowImePostLayout(target);
assertTrue(mImeProvider.isImeTargetFromDisplayContentAndImeSame());
}
@Test
public void testIsImeShowing() {
WindowState ime = createWindow(null, TYPE_INPUT_METHOD, "ime");
makeWindowVisibleAndDrawn(ime);
mImeProvider.setWindow(ime, null, null);
WindowState target = createWindow(null, TYPE_APPLICATION, "app");
mDisplayContent.mInputMethodTarget = target;
mDisplayContent.mInputMethodControlTarget = target;
mImeProvider.scheduleShowImePostLayout(target);
assertFalse(mImeProvider.isImeShowing());
mImeProvider.checkShowImePostLayout();
assertTrue(mImeProvider.isImeShowing());
mImeProvider.setImeShowing(false);
assertFalse(mImeProvider.isImeShowing());
}
}

View File

@@ -37,6 +37,8 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.server.wm.WindowStateAnimator.HAS_DRAWN;
import static org.mockito.Mockito.mock;
import android.content.Context;
@@ -261,6 +263,13 @@ class WindowTestsBase extends SystemServiceTestsBase {
}
}
static void makeWindowVisibleAndDrawn(WindowState... windows) {
makeWindowVisible(windows);
for (WindowState win : windows) {
win.mWinAnimator.mDrawState = HAS_DRAWN;
}
}
/** Creates a {@link ActivityStack} and adds it to the specified {@link DisplayContent}. */
ActivityStack createTaskStackOnDisplay(DisplayContent dc) {
return createTaskStackOnDisplay(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, dc);