Merge "Fix hiding keyboard animation stuck while dialog dismissing." into rvc-dev am: dac09ee7fe am: 0a49dd38a2 am: 869a1892db

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/12174530

Change-Id: Iac68c18c16c10c794e1f462ccaedeed656fc6a5b
This commit is contained in:
Adrian Roos
2020-07-17 21:51:58 +00:00
committed by Automerger Merge Worker
4 changed files with 39 additions and 44 deletions

View File

@@ -125,10 +125,10 @@ public final class ImeFocusController {
final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView; final View viewForWindowFocus = focusedView != null ? focusedView : mViewRootImpl.mView;
onViewFocusChanged(viewForWindowFocus, true); onViewFocusChanged(viewForWindowFocus, true);
// Starting new input when the next focused view is same as served view but the // Starting new input when the next focused view is same as served view but the currently
// editor is not aligned with the same editor or editor is inactive. // active connection (if any) is not associated with it.
final boolean nextFocusIsServedView = mServedView != null && mServedView == focusedView; final boolean nextFocusIsServedView = mServedView == viewForWindowFocus;
if (nextFocusIsServedView && !immDelegate.isSameEditorAndAcceptingText(focusedView)) { if (nextFocusIsServedView && !immDelegate.hasActiveConnection(viewForWindowFocus)) {
forceFocus = true; forceFocus = true;
} }
@@ -254,7 +254,7 @@ public final class ImeFocusController {
void setCurrentRootView(ViewRootImpl rootView); void setCurrentRootView(ViewRootImpl rootView);
boolean isCurrentRootView(ViewRootImpl rootView); boolean isCurrentRootView(ViewRootImpl rootView);
boolean isRestartOnNextWindowFocus(boolean reset); boolean isRestartOnNextWindowFocus(boolean reset);
boolean isSameEditorAndAcceptingText(View view); boolean hasActiveConnection(View view);
} }
public View getServedView() { public View getServedView() {

View File

@@ -19,8 +19,8 @@ package android.view.inputmethod;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL; import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS; import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR; import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION;
import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR; import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION;
import android.annotation.DrawableRes; import android.annotation.DrawableRes;
import android.annotation.NonNull; import android.annotation.NonNull;
@@ -89,6 +89,7 @@ import com.android.internal.view.InputBindResult;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
@@ -610,14 +611,13 @@ public final class InputMethodManager {
@Override @Override
public void startInputAsyncOnWindowFocusGain(View focusedView, public void startInputAsyncOnWindowFocusGain(View focusedView,
@SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) { @SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) {
final boolean forceNewFocus1 = forceNewFocus;
final int startInputFlags = getStartInputFlags(focusedView, 0); final int startInputFlags = getStartInputFlags(focusedView, 0);
final ImeFocusController controller = getFocusController(); final ImeFocusController controller = getFocusController();
if (controller == null) { if (controller == null) {
return; return;
} }
if (controller.checkFocus(forceNewFocus1, false)) { if (controller.checkFocus(forceNewFocus, false)) {
// We need to restart input on the current focus view. This // We need to restart input on the current focus view. This
// should be done in conjunction with telling the system service // should be done in conjunction with telling the system service
// about the window gaining focus, to help make the transition // about the window gaining focus, to help make the transition
@@ -633,15 +633,15 @@ public final class InputMethodManager {
// we'll just do a window focus gain and call it a day. // we'll just do a window focus gain and call it a day.
try { try {
View servedView = controller.getServedView(); View servedView = controller.getServedView();
boolean nextFocusSameEditor = servedView != null && servedView == focusedView boolean nextFocusHasConnection = servedView != null && servedView == focusedView
&& isSameEditorAndAcceptingText(focusedView); && hasActiveConnection(focusedView);
if (DEBUG) { if (DEBUG) {
Log.v(TAG, "Reporting focus gain, without startInput" Log.v(TAG, "Reporting focus gain, without startInput"
+ ", nextFocusIsServedView=" + nextFocusSameEditor); + ", nextFocusIsServedView=" + nextFocusHasConnection);
} }
final int startInputReason = final int startInputReason =
nextFocusSameEditor ? WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR nextFocusHasConnection ? WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION
: WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR; : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION;
mService.startInputOrWindowGainedFocus( mService.startInputOrWindowGainedFocus(
startInputReason, mClient, startInputReason, mClient,
focusedView.getWindowToken(), startInputFlags, softInputMode, focusedView.getWindowToken(), startInputFlags, softInputMode,
@@ -701,33 +701,24 @@ public final class InputMethodManager {
} }
/** /**
* For {@link ImeFocusController} to check if the given focused view aligns with the same * Checks whether the active input connection (if any) is for the given view.
* editor and the editor is active to accept the text input.
* *
* TODO(b/160968797): Remove this method and move mCurrentTextBoxAttritube to * TODO(b/160968797): Remove this method and move mServedInputConnectionWrapper to
* ImeFocusController. * ImeFocusController.
* In the long-term, we should make mCurrentTextBoxAtrtribue as per-window base instance,
* so that we we can directly check if the current focused view aligned with the same editor
* in the window without using this checking.
* *
* Note that this method is only use for fixing start new input may ignored issue * Note that this method is only intended for restarting input after focus gain
* (e.g. b/160391516), DO NOT leverage this method to do another check. * (e.g. b/160391516), DO NOT leverage this method to do another check.
*/ */
public boolean isSameEditorAndAcceptingText(View view) { @Override
public boolean hasActiveConnection(View view) {
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null) { if (!hasServedByInputMethodLocked(view)) {
return false; return false;
} }
final EditorInfo ic = mCurrentTextBoxAttribute; return mServedInputConnectionWrapper != null
// This sameEditor checking is based on using object hash comparison to check if && mServedInputConnectionWrapper.isActive()
// some fields of the current EditorInfo (e.g. autoFillId, OpPackageName) the && mServedInputConnectionWrapper.mServedView.get() == view;
// hash code is same as the given focused view.
final boolean sameEditor = view.onCheckIsTextEditor() && view.getId() == ic.fieldId
&& view.getAutofillId() == ic.autofillId
&& view.getContext().getOpPackageName() == ic.packageName;
return sameEditor && mServedInputConnectionWrapper != null
&& mServedInputConnectionWrapper.isActive();
} }
} }
} }
@@ -980,11 +971,13 @@ public final class InputMethodManager {
private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper { private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
private final InputMethodManager mParentInputMethodManager; private final InputMethodManager mParentInputMethodManager;
private final WeakReference<View> mServedView;
public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn, ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn,
final InputMethodManager inputMethodManager) { InputMethodManager inputMethodManager, View servedView) {
super(mainLooper, conn); super(mainLooper, conn);
mParentInputMethodManager = inputMethodManager; mParentInputMethodManager = inputMethodManager;
mServedView = new WeakReference<>(servedView);
} }
@Override @Override
@@ -1007,6 +1000,7 @@ public final class InputMethodManager {
+ "connection=" + getInputConnection() + "connection=" + getInputConnection()
+ " finished=" + isFinished() + " finished=" + isFinished()
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
+ " mServedView=" + mServedView.get()
+ "}"; + "}";
} }
} }
@@ -1187,7 +1181,8 @@ public final class InputMethodManager {
mMainLooper = looper; mMainLooper = looper;
mH = new H(looper); mH = new H(looper);
mDisplayId = displayId; mDisplayId = displayId;
mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this); mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this,
null);
} }
/** /**
@@ -1968,7 +1963,7 @@ public final class InputMethodManager {
icHandler = ic.getHandler(); icHandler = ic.getHandler();
} }
servedContext = new ControlledInputConnectionWrapper( servedContext = new ControlledInputConnectionWrapper(
icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this); icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view);
} else { } else {
servedContext = null; servedContext = null;
missingMethodFlags = 0; missingMethodFlags = 0;

View File

@@ -46,10 +46,10 @@ public final class InputMethodDebug {
return "UNSPECIFIED"; return "UNSPECIFIED";
case StartInputReason.WINDOW_FOCUS_GAIN: case StartInputReason.WINDOW_FOCUS_GAIN:
return "WINDOW_FOCUS_GAIN"; return "WINDOW_FOCUS_GAIN";
case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR: case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION:
return "WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR"; return "WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION";
case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR: case StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION:
return "WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR"; return "WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION";
case StartInputReason.APP_CALLED_RESTART_INPUT_API: case StartInputReason.APP_CALLED_RESTART_INPUT_API:
return "APP_CALLED_RESTART_INPUT_API"; return "APP_CALLED_RESTART_INPUT_API";
case StartInputReason.CHECK_FOCUS: case StartInputReason.CHECK_FOCUS:

View File

@@ -30,8 +30,8 @@ import java.lang.annotation.Retention;
@IntDef(value = { @IntDef(value = {
StartInputReason.UNSPECIFIED, StartInputReason.UNSPECIFIED,
StartInputReason.WINDOW_FOCUS_GAIN, StartInputReason.WINDOW_FOCUS_GAIN,
StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR, StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION,
StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR, StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION,
StartInputReason.APP_CALLED_RESTART_INPUT_API, StartInputReason.APP_CALLED_RESTART_INPUT_API,
StartInputReason.CHECK_FOCUS, StartInputReason.CHECK_FOCUS,
StartInputReason.BOUND_TO_IMMS, StartInputReason.BOUND_TO_IMMS,
@@ -54,13 +54,13 @@ public @interface StartInputReason {
* view and its input connection remains. {@link android.view.inputmethod.InputMethodManager} * view and its input connection remains. {@link android.view.inputmethod.InputMethodManager}
* just reports this window focus change event to sync IME input target for system. * just reports this window focus change event to sync IME input target for system.
*/ */
int WINDOW_FOCUS_GAIN_REPORT_WITH_SAME_EDITOR = 2; int WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION = 2;
/** /**
* {@link android.view.Window} gained focus but there is no {@link android.view.View} that is * {@link android.view.Window} gained focus but there is no {@link android.view.View} that is
* eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports * eligible to have IME focus. {@link android.view.inputmethod.InputMethodManager} just reports
* this window focus change event for logging. * this window focus change event for logging.
*/ */
int WINDOW_FOCUS_GAIN_REPORT_WITHOUT_EDITOR = 3; int WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION = 3;
/** /**
* {@link android.view.inputmethod.InputMethodManager#restartInput(android.view.View)} is * {@link android.view.inputmethod.InputMethodManager#restartInput(android.view.View)} is
* either explicitly called by the application or indirectly called by some Framework class * either explicitly called by the application or indirectly called by some Framework class