Merge "ImeVisibilityApplier: fix hideIme no-op for Embedded display case." into udc-dev

This commit is contained in:
Ming-Shin Lu
2023-03-16 01:04:24 +00:00
committed by Android (Google) Code Review
4 changed files with 61 additions and 9 deletions

View File

@@ -136,17 +136,16 @@ final class DefaultImeVisibilityApplier implements ImeVisibilityApplier {
mWindowManagerInternal.showImePostLayout(windowToken, statsToken); mWindowManagerInternal.showImePostLayout(windowToken, statsToken);
break; break;
case STATE_HIDE_IME: case STATE_HIDE_IME:
if (mService.mCurFocusedWindowClient != null) { if (mService.hasAttachedClient()) {
ImeTracker.forLogging().onProgress(statsToken, ImeTracker.forLogging().onProgress(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY); ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
// IMMS only knows of focused window, not the actual IME target. // IMMS only knows of focused window, not the actual IME target.
// e.g. it isn't aware of any window that has both // e.g. it isn't aware of any window that has both
// NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target. // NOT_FOCUSABLE, ALT_FOCUSABLE_IM flags set and can the IME target.
// Send it to window manager to hide IME from IME target window. // Send it to window manager to hide IME from the actual IME control target
// TODO(b/139861270): send to mCurClient.client once IMMS is aware of // of the target display.
// actual IME target.
mWindowManagerInternal.hideIme(windowToken, mWindowManagerInternal.hideIme(windowToken,
mService.mCurFocusedWindowClient.mSelfReportedDisplayId, statsToken); mService.getDisplayIdToShowImeLocked(), statsToken);
} else { } else {
ImeTracker.forLogging().onFailed(statsToken, ImeTracker.forLogging().onFailed(statsToken,
ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY); ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);

View File

@@ -2339,6 +2339,19 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
} }
} }
/** {@code true} when a {@link ClientState} has attached from starting the input connection. */
@GuardedBy("ImfLock.class")
boolean hasAttachedClient() {
return mCurClient != null;
}
@VisibleForTesting
void setAttachedClientForTesting(@NonNull ClientState cs) {
synchronized (ImfLock.class) {
mCurClient = cs;
}
}
@GuardedBy("ImfLock.class") @GuardedBy("ImfLock.class")
void clearInputShownLocked() { void clearInputShownLocked() {
mVisibilityStateComputer.setInputShown(false); mVisibilityStateComputer.setInputShown(false);

View File

@@ -740,7 +740,7 @@ public abstract class WindowManagerInternal {
/** /**
* Show IME on imeTargetWindow once IME has finished layout. * Show IME on imeTargetWindow once IME has finished layout.
* *
* @param imeTargetWindowToken token of the (IME target) window on which IME should be shown. * @param imeTargetWindowToken token of the (IME target) window which IME should be shown.
* @param statsToken the token tracking the current IME show request or {@code null} otherwise. * @param statsToken the token tracking the current IME show request or {@code null} otherwise.
*/ */
public abstract void showImePostLayout(IBinder imeTargetWindowToken, public abstract void showImePostLayout(IBinder imeTargetWindowToken,
@@ -749,7 +749,7 @@ public abstract class WindowManagerInternal {
/** /**
* Hide IME using imeTargetWindow when requested. * Hide IME using imeTargetWindow when requested.
* *
* @param imeTargetWindowToken token of the (IME target) window on which IME should be hidden. * @param imeTargetWindowToken token of the (IME target) window on which requests hiding IME.
* @param displayId the id of the display the IME is on. * @param displayId the id of the display the IME is on.
* @param statsToken the token tracking the current IME hide request or {@code null} otherwise. * @param statsToken the token tracking the current IME hide request or {@code null} otherwise.
*/ */

View File

@@ -17,6 +17,7 @@
package com.android.server.inputmethod; package com.android.server.inputmethod;
import static android.inputmethodservice.InputMethodService.IME_ACTIVE; import static android.inputmethodservice.InputMethodService.IME_ACTIVE;
import static android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE;
import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_SOFT_INPUT; import static com.android.internal.inputmethod.SoftInputShowHideReason.HIDE_SOFT_INPUT;
import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_SOFT_INPUT; import static com.android.internal.inputmethod.SoftInputShowHideReason.SHOW_SOFT_INPUT;
@@ -35,11 +36,16 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException; import android.os.RemoteException;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.inputmethod.InputBindResult;
import com.android.internal.inputmethod.StartInputFlags;
import com.android.internal.inputmethod.StartInputReason;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -60,8 +66,8 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
super.setUp(); super.setUp();
mVisibilityApplier = mVisibilityApplier =
(DefaultImeVisibilityApplier) mInputMethodManagerService.getVisibilityApplier(); (DefaultImeVisibilityApplier) mInputMethodManagerService.getVisibilityApplier();
mInputMethodManagerService.mCurFocusedWindowClient = mock( mInputMethodManagerService.setAttachedClientForTesting(
InputMethodManagerService.ClientState.class); mock(InputMethodManagerService.ClientState.class));
} }
@Test @Test
@@ -119,4 +125,38 @@ public class DefaultImeVisibilityApplierTest extends InputMethodManagerServiceTe
mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_SHOW_IME_IMPLICIT); mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_SHOW_IME_IMPLICIT);
verifyShowSoftInput(true, true, InputMethodManager.SHOW_IMPLICIT); verifyShowSoftInput(true, true, InputMethodManager.SHOW_IMPLICIT);
} }
@Test
public void testApplyImeVisibility_hideImeFromTargetOnSecondaryDisplay() {
// Init a IME target client on the secondary display to show IME.
mInputMethodManagerService.addClient(mMockInputMethodClient, mMockRemoteInputConnection,
10 /* selfReportedDisplayId */);
mInputMethodManagerService.setAttachedClientForTesting(null);
startInputOrWindowGainedFocus(mWindowToken, SOFT_INPUT_STATE_ALWAYS_VISIBLE);
synchronized (ImfLock.class) {
final int displayIdToShowIme = mInputMethodManagerService.getDisplayIdToShowImeLocked();
// Verify hideIme will apply the expected displayId when the default IME
// visibility applier app STATE_HIDE_IME.
mVisibilityApplier.applyImeVisibility(mWindowToken, null, STATE_HIDE_IME);
verify(mInputMethodManagerService.mWindowManagerInternal).hideIme(
eq(mWindowToken), eq(displayIdToShowIme), eq(null));
}
}
private InputBindResult startInputOrWindowGainedFocus(IBinder windowToken, int softInputMode) {
return mInputMethodManagerService.startInputOrWindowGainedFocus(
StartInputReason.WINDOW_FOCUS_GAIN /* startInputReason */,
mMockInputMethodClient /* client */,
windowToken /* windowToken */,
StartInputFlags.VIEW_HAS_FOCUS | StartInputFlags.IS_TEXT_EDITOR,
softInputMode /* softInputMode */,
0 /* windowFlags */,
mEditorInfo /* editorInfo */,
mMockRemoteInputConnection /* inputConnection */,
mMockRemoteAccessibilityInputConnection /* remoteAccessibilityInputConnection */,
mTargetSdkVersion /* unverifiedTargetSdkVersion */,
mCallingUserId /* userId */,
mMockImeOnBackInvokedDispatcher /* imeDispatcher */);
}
} }