[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:
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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 */,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user