Merge "Pipe windowToken for hideSoftInput" into rvc-dev am: 73b1d16d28 am: cec5307235 am: ef8ebae6e5

Change-Id: I391a3ee0e19695ae5b34a8afb329c14bef31b8e5
This commit is contained in:
Automerger Merge Worker
2020-02-27 07:52:52 +00:00
12 changed files with 158 additions and 55 deletions

View File

@@ -219,22 +219,29 @@ class IInputMethodWrapper extends IInputMethod.Stub
case DO_REVOKE_SESSION:
inputMethod.revokeSession((InputMethodSession)msg.obj);
return;
case DO_SHOW_SOFT_INPUT:
SomeArgs args = (SomeArgs)msg.obj;
case DO_SHOW_SOFT_INPUT: {
final SomeArgs args = (SomeArgs)msg.obj;
inputMethod.showSoftInputWithToken(
msg.arg1, (ResultReceiver) args.arg2, (IBinder) args.arg1);
args.recycle();
return;
case DO_HIDE_SOFT_INPUT:
inputMethod.hideSoftInput(msg.arg1, (ResultReceiver)msg.obj);
}
case DO_HIDE_SOFT_INPUT: {
final SomeArgs args = (SomeArgs) msg.obj;
inputMethod.hideSoftInputWithToken(msg.arg1, (ResultReceiver) args.arg2,
(IBinder) args.arg1);
args.recycle();
return;
}
case DO_CHANGE_INPUTMETHOD_SUBTYPE:
inputMethod.changeInputMethodSubtype((InputMethodSubtype)msg.obj);
return;
case DO_CREATE_INLINE_SUGGESTIONS_REQUEST:
args = (SomeArgs) msg.obj;
final SomeArgs args = (SomeArgs) msg.obj;
inputMethod.onCreateInlineSuggestionsRequest(
(InlineSuggestionsRequestInfo) args.arg1,
(IInlineSuggestionsRequestCallback) args.arg2);
args.recycle();
return;
}
@@ -380,9 +387,9 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIO(DO_HIDE_SOFT_INPUT,
flags, resultReceiver));
public void hideSoftInput(IBinder hideInputToken, int flags, ResultReceiver resultReceiver) {
mCaller.executeOrSendMessage(mCaller.obtainMessageIOO(DO_HIDE_SOFT_INPUT,
flags, hideInputToken, resultReceiver));
}
@BinderThread

View File

@@ -459,6 +459,16 @@ public class InputMethodService extends AbstractInputMethodService {
*/
private IBinder mCurShowInputToken;
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#hideSoftInput}
* The original app window token is passed from client app window.
* {@link com.android.server.inputmethod.InputMethodManagerService} creates a unique dummy
* token to identify this window.
* This dummy token is only valid for a single call to {@link InputMethodImpl#hideSoftInput},
* after which it is set {@code null} until next call.
*/
private IBinder mCurHideInputToken;
final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer = info -> {
onComputeInsets(mTmpInsets);
if (isExtractViewShown()) {
@@ -500,6 +510,7 @@ public class InputMethodService extends AbstractInputMethodService {
public class InputMethodImpl extends AbstractInputMethodImpl {
private boolean mSystemCallingShowSoftInput;
private boolean mSystemCallingHideSoftInput;
/**
* {@inheritDoc}
@@ -634,6 +645,21 @@ public class InputMethodService extends AbstractInputMethodService {
}
}
/**
* {@inheritDoc}
* @hide
*/
@MainThread
@Override
public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver,
IBinder hideInputToken) {
mSystemCallingHideSoftInput = true;
mCurHideInputToken = hideInputToken;
hideSoftInput(flags, resultReceiver);
mCurHideInputToken = null;
mSystemCallingHideSoftInput = false;
}
/**
* {@inheritDoc}
*/
@@ -641,6 +667,12 @@ public class InputMethodService extends AbstractInputMethodService {
@Override
public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
if (DEBUG) Log.v(TAG, "hideSoftInput()");
if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R
&& !mSystemCallingHideSoftInput) {
Log.e(TAG, "IME shouldn't call hideSoftInput on itself."
+ " Use requestHideSelf(int) itself");
return;
}
final boolean wasVisible = mIsPreRendered
? mDecorViewVisible && mWindowVisible : isInputViewShown();
applyVisibilityInInsetsConsumerIfNecessary(false /* setVisible */);
@@ -738,6 +770,15 @@ public class InputMethodService extends AbstractInputMethodService {
public void setCurrentShowInputToken(IBinder showInputToken) {
mCurShowInputToken = showInputToken;
}
/**
* {@inheritDoc}
* @hide
*/
@Override
public void setCurrentHideInputToken(IBinder hideInputToken) {
mCurHideInputToken = hideInputToken;
}
}
// TODO(b/137800469): Add detailed docs explaining the inline suggestions process.
@@ -2172,7 +2213,8 @@ public class InputMethodService extends AbstractInputMethodService {
if (!isVisibilityAppliedUsingInsetsConsumer()) {
return;
}
mPrivOps.applyImeVisibility(mCurShowInputToken, setVisible);
mPrivOps.applyImeVisibility(setVisible
? mCurShowInputToken : mCurHideInputToken, setVisible);
}
private boolean isVisibilityAppliedUsingInsetsConsumer() {

View File

@@ -348,6 +348,27 @@ public interface InputMethod {
* {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN InputMethodManager.RESULT_UNCHANGED_HIDDEN},
* {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
* {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
* @param hideInputToken an opaque {@link android.os.Binder} token to identify which API call
* of {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}} is associated
* with this callback.
* @hide
*/
@MainThread
public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver,
IBinder hideInputToken);
/**
* Request that any soft input part of the input method be hidden from the user.
* @param flags Provides additional information about the show request.
* Currently always 0.
* @param resultReceiver The client requesting the show may wish to
* be told the impact of their request, which should be supplied here.
* The result code should be
* {@link InputMethodManager#RESULT_UNCHANGED_SHOWN InputMethodManager.RESULT_UNCHANGED_SHOWN},
* {@link InputMethodManager#RESULT_UNCHANGED_HIDDEN
* InputMethodManager.RESULT_UNCHANGED_HIDDEN},
* {@link InputMethodManager#RESULT_SHOWN InputMethodManager.RESULT_SHOWN}, or
* {@link InputMethodManager#RESULT_HIDDEN InputMethodManager.RESULT_HIDDEN}.
*/
@MainThread
public void hideSoftInput(int flags, ResultReceiver resultReceiver);
@@ -366,4 +387,13 @@ public interface InputMethod {
* @hide
*/
public void setCurrentShowInputToken(IBinder showInputToken);
/**
* Update token of the client window requesting {@link #hideSoftInput(int, ResultReceiver)}
* @param hideInputToken dummy app window token for window requesting
* {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}
* @hide
*/
public void setCurrentHideInputToken(IBinder hideInputToken);
}

View File

@@ -1709,7 +1709,7 @@ public final class InputMethodManager {
}
try {
return mService.hideSoftInput(mClient, flags, resultReceiver);
return mService.hideSoftInput(mClient, windowToken, flags, resultReceiver);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1986,7 +1986,8 @@ public final class InputMethodManager {
@UnsupportedAppUsage
void closeCurrentInput() {
try {
mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
mService.hideSoftInput(
mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -41,5 +41,5 @@ interface IInputMethodPrivilegedOperations {
boolean shouldOfferSwitchingToNextInputMethod();
void notifyUserAction();
void reportPreRendered(in EditorInfo info);
void applyImeVisibility(IBinder showInputToken, boolean setVisible);
void applyImeVisibility(IBinder showOrHideInputToken, boolean setVisible);
}

View File

@@ -371,18 +371,20 @@ public final class InputMethodPrivilegedOperations {
/**
* Calls {@link IInputMethodPrivilegedOperations#applyImeVisibility(IBinder, boolean)}.
*
* @param showInputToken dummy token that maps to window requesting
* {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)}
* @param showOrHideInputToken dummy token that maps to window requesting
* {@link android.view.inputmethod.InputMethodManager#showSoftInput(View, int)} or
* {@link android.view.inputmethod.InputMethodManager#hideSoftInputFromWindow
* (IBinder, int)}
* @param setVisible {@code true} to set IME visible, else hidden.
*/
@AnyThread
public void applyImeVisibility(IBinder showInputToken, boolean setVisible) {
public void applyImeVisibility(IBinder showOrHideInputToken, boolean setVisible) {
final IInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
if (ops == null) {
return;
}
try {
ops.applyImeVisibility(showInputToken, setVisible);
ops.applyImeVisibility(showOrHideInputToken, setVisible);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -55,7 +55,7 @@ oneway interface IInputMethod {
void showSoftInput(in IBinder showInputToken, int flags, in ResultReceiver resultReceiver);
void hideSoftInput(int flags, in ResultReceiver resultReceiver);
void hideSoftInput(in IBinder hideInputToken, int flags, in ResultReceiver resultReceiver);
void changeInputMethodSubtype(in InputMethodSubtype subtype);
}

View File

@@ -43,7 +43,7 @@ interface IInputMethodManager {
boolean showSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
in ResultReceiver resultReceiver);
boolean hideSoftInput(in IInputMethodClient client, int flags,
boolean hideSoftInput(in IInputMethodClient client, IBinder windowToken, int flags,
in ResultReceiver resultReceiver);
// If windowToken is null, this just does startInput(). Otherwise this reports that a window
// has gained focus, and if 'attribute' is non-null then also does startInput.

View File

@@ -845,6 +845,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@GuardedBy("mMethodMap")
private final WeakHashMap<IBinder, IBinder> mShowRequestWindowMap = new WeakHashMap<>();
/**
* Map of generated token to windowToken that is requesting
* {@link InputMethodManager#hideSoftInputFromWindow(IBinder, int)}.
* This map tracks origin of hideSoftInput requests.
*/
@GuardedBy("mMethodMap")
private final WeakHashMap<IBinder, IBinder> mHideRequestWindowMap = new WeakHashMap<>();
/**
* A ring buffer to store the history of {@link StartInputInfo}.
*/
@@ -1064,7 +1072,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
== AccessibilityService.SHOW_MODE_HIDDEN;
if (mAccessibilityRequestingNoSoftKeyboard) {
final boolean showRequested = mShowRequested;
hideCurrentInputLocked(0, null,
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
SoftInputShowHideReason.HIDE_SETTINGS_ON_CHANGE);
mShowRequested = showRequested;
} else if (mShowRequested) {
@@ -1695,7 +1703,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// TODO: Is it really possible that switchUserLocked() happens before system ready?
if (mSystemReady) {
hideCurrentInputLocked(0, null, SoftInputShowHideReason.HIDE_SWITCH_USER);
hideCurrentInputLocked(
mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_SWITCH_USER);
resetCurrentMethodAndClient(UnbindReason.SWITCH_USER);
buildInputMethodListLocked(initialUserSwitch);
if (TextUtils.isEmpty(mSettings.getSelectedInputMethod())) {
@@ -3040,7 +3050,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
@Override
public boolean hideSoftInput(IInputMethodClient client, int flags,
public boolean hideSoftInput(IInputMethodClient client, IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
int uid = Binder.getCallingUid();
synchronized (mMethodMap) {
@@ -3068,7 +3078,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
return hideCurrentInputLocked(flags, resultReceiver,
return hideCurrentInputLocked(windowToken, flags, resultReceiver,
SoftInputShowHideReason.HIDE_SOFT_INPUT);
} finally {
Binder.restoreCallingIdentity(ident);
@@ -3076,7 +3086,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
}
boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver,
boolean hideCurrentInputLocked(IBinder windowToken, int flags, ResultReceiver resultReceiver,
@SoftInputShowHideReason int reason) {
if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
&& (mShowExplicitlyRequested || mShowForced)) {
@@ -3100,12 +3110,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
(mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
boolean res;
if (shouldHideSoftInput) {
final Binder hideInputToken = new Binder();
mHideRequestWindowMap.put(hideInputToken, windowToken);
// The IME will report its visible state again after the following message finally
// delivered to the IME process as an IPC. Hence the inconsistency between
// IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
// the final state.
executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(MSG_HIDE_SOFT_INPUT,
reason, mCurMethod, resultReceiver));
executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOOO(MSG_HIDE_SOFT_INPUT,
reason, mCurMethod, resultReceiver, hideInputToken));
res = true;
} else {
res = false;
@@ -3242,7 +3254,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Slog.w(TAG, "If you need to impersonate a foreground user/profile from"
+ " a background user, use EditorInfo.targetInputMethodUser with"
+ " INTERACT_ACROSS_USERS_FULL permission.");
hideCurrentInputLocked(0, null, SoftInputShowHideReason.HIDE_INVALID_USER);
hideCurrentInputLocked(
mCurFocusedWindow, 0, null, SoftInputShowHideReason.HIDE_INVALID_USER);
return InputBindResult.INVALID_USER;
}
@@ -3305,7 +3318,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// be behind any soft input window, so hide the
// soft input window if it is shown.
if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null,
hideCurrentInputLocked(
mCurFocusedWindow, InputMethodManager.HIDE_NOT_ALWAYS, null,
SoftInputShowHideReason.HIDE_UNSPECIFIED_WINDOW);
// If focused display changed, we should unbind current method
@@ -3342,13 +3356,13 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case LayoutParams.SOFT_INPUT_STATE_HIDDEN:
if ((softInputMode & LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
hideCurrentInputLocked(0, null,
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
SoftInputShowHideReason.HIDE_STATE_HIDDEN_FORWARD_NAV);
}
break;
case LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
if (DEBUG) Slog.v(TAG, "Window asks to hide input");
hideCurrentInputLocked(0, null,
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
SoftInputShowHideReason.HIDE_ALWAYS_HIDDEN_STATE);
break;
case LayoutParams.SOFT_INPUT_STATE_VISIBLE:
@@ -3832,7 +3846,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
// Send it to window manager to hide IME from IME target window.
// TODO(b/139861270): send to mCurClient.client once IMMS is aware of
// actual IME target.
mWindowManagerInternal.hideIme(mCurClient.selfReportedDisplayId);
mWindowManagerInternal.hideIme(mHideRequestWindowMap.get(windowToken));
}
} else {
// Send to window manager to show IME after IME layout finishes.
@@ -3872,7 +3886,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
long ident = Binder.clearCallingIdentity();
try {
hideCurrentInputLocked(flags, null, SoftInputShowHideReason.HIDE_MY_SOFT_INPUT);
hideCurrentInputLocked(
mLastImeTargetWindow, flags, null,
SoftInputShowHideReason.HIDE_MY_SOFT_INPUT);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -3969,11 +3986,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
args.recycle();
return true;
case MSG_SHOW_SOFT_INPUT:
args = (SomeArgs)msg.obj;
args = (SomeArgs) msg.obj;
try {
final @SoftInputShowHideReason int reason = msg.arg2;
if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
+ msg.arg1 + ", " + args.arg2 + ") for reason: "
+ args.arg3 + ", " + msg.arg1 + ", " + args.arg2 + ") for reason: "
+ InputMethodDebug.softInputDisplayReasonToString(reason));
((IInputMethod) args.arg1).showSoftInput(
(IBinder) args.arg3, msg.arg1, (ResultReceiver) args.arg2);
@@ -3986,13 +4003,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
args.recycle();
return true;
case MSG_HIDE_SOFT_INPUT:
args = (SomeArgs)msg.obj;
args = (SomeArgs) msg.obj;
try {
final @SoftInputShowHideReason int reason = msg.arg1;
if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
+ args.arg2 + ") for reason: "
+ args.arg3 + ", " + args.arg2 + ") for reason: "
+ InputMethodDebug.softInputDisplayReasonToString(reason));
((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
((IInputMethod)args.arg1).hideSoftInput(
(IBinder) args.arg3, 0, (ResultReceiver)args.arg2);
mSoftInputShowHideHistory.addEntry(
new SoftInputShowHideHistory.Entry(mCurClient,
InputMethodDebug.objToString(mCurFocusedWindow),
@@ -4004,7 +4022,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
case MSG_HIDE_CURRENT_INPUT_METHOD:
synchronized (mMethodMap) {
final @SoftInputShowHideReason int reason = (int) msg.obj;
hideCurrentInputLocked(0, null, reason);
hideCurrentInputLocked(mCurFocusedWindow, 0, null, reason);
}
return true;
case MSG_INITIALIZE_IME:
@@ -5409,7 +5428,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
final String nextIme;
final List<InputMethodInfo> nextEnabledImes;
if (userId == mSettings.getCurrentUserId()) {
hideCurrentInputLocked(0, null,
hideCurrentInputLocked(mCurFocusedWindow, 0, null,
SoftInputShowHideReason.HIDE_RESET_SHELL_COMMAND);
unbindCurrentMethodLocked();
// Reset the current IME

View File

@@ -1500,7 +1500,8 @@ public final class MultiClientInputMethodManagerService {
@BinderThread
@Override
public boolean hideSoftInput(
IInputMethodClient client, int flags, ResultReceiver resultReceiver) {
IInputMethodClient client, IBinder windowToken, int flags,
ResultReceiver resultReceiver) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int userId = UserHandle.getUserId(callingUid);

View File

@@ -527,9 +527,9 @@ public abstract class WindowManagerInternal {
/**
* Hide IME using imeTargetWindow when requested.
*
* @param displayId on which IME is shown
* @param imeTargetWindowToken token of the (IME target) window on which IME should be hidden.
*/
public abstract void hideIme(int displayId);
public abstract void hideIme(IBinder imeTargetWindowToken);
/**
* Tell window manager about a package that should not be running with high refresh rate

View File

@@ -7441,27 +7441,28 @@ public class WindowManagerService extends IWindowManager.Stub
return;
}
imeTarget = imeTarget.getImeControlTarget();
final int displayId = imeTarget.getDisplayId();
mRoot.getDisplayContent(displayId).getInsetsStateController().getImeSourceProvider()
imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider()
.scheduleShowImePostLayout(imeTarget);
}
}
@Override
public void hideIme(int displayId) {
public void hideIme(IBinder imeTargetWindowToken) {
synchronized (mGlobalLock) {
final DisplayContent dc = mRoot.getDisplayContent(displayId);
if (dc != null) {
InsetsControlTarget imeControlTarget = dc.mInputMethodControlTarget;
if (imeControlTarget == null) {
return;
}
// If there was a pending IME show(), reset it as IME has been
// requested to be hidden.
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
imeControlTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
WindowState imeTarget = mWindowMap.get(imeTargetWindowToken);
if (imeTarget == null) {
// The target window no longer exists.
return;
}
final DisplayContent dc = imeTarget.getImeControlTarget().getDisplayContent();
// If there was a pending IME show(), reset it as IME has been
// requested to be hidden.
dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
if (dc.mInputMethodControlTarget == null) {
return;
}
dc.mInputMethodControlTarget.hideInsets(
WindowInsets.Type.ime(), true /* fromIme */);
}
}