Merge "Introduce InputMethodSessionWrapper for InputMethodManager" into sc-dev

This commit is contained in:
Wilson Wu
2021-03-19 02:05:02 +00:00
committed by Android (Google) Code Review
2 changed files with 251 additions and 109 deletions

View File

@@ -462,11 +462,25 @@ public final class InputMethodManager {
*/ */
@UnsupportedAppUsage @UnsupportedAppUsage
String mCurId; String mCurId;
/** /**
* The actual instance of the method to make calls on it. * Kept for {@link UnsupportedAppUsage}. Not officially maintained.
*
* @deprecated New code should use {@link #mCurrentInputMethodSession}.
*/ */
@Deprecated
@GuardedBy("mH")
@Nullable
@UnsupportedAppUsage @UnsupportedAppUsage
IInputMethodSession mCurMethod; IInputMethodSession mCurMethod;
/**
* Encapsulates IPCs to the currently connected InputMethodService.
*/
@Nullable
@GuardedBy("mH")
private InputMethodSessionWrapper mCurrentInputMethodSession = null;
InputChannel mCurChannel; InputChannel mCurChannel;
ImeInputEventSender mCurSender; ImeInputEventSender mCurSender;
@@ -623,11 +637,8 @@ public final class InputMethodManager {
public void finishInputAndReportToIme() { public void finishInputAndReportToIme() {
synchronized (mH) { synchronized (mH) {
finishInputLocked(); finishInputLocked();
if (mCurMethod != null) { if (mCurrentInputMethodSession != null) {
try { mCurrentInputMethodSession.finishInput();
mCurMethod.finishInput();
} catch (RemoteException e) {
}
} }
} }
} }
@@ -754,7 +765,8 @@ public final class InputMethodManager {
@Override @Override
public boolean hasActiveConnection(View view) { public boolean hasActiveConnection(View view) {
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurMethod == null) { if (!hasServedByInputMethodLocked(view)
|| mCurrentInputMethodSession == null) {
return false; return false;
} }
@@ -861,7 +873,9 @@ public final class InputMethodManager {
REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
setInputChannelLocked(res.channel); setInputChannelLocked(res.channel);
mCurMethod = res.method; mCurMethod = res.method; // for @UnsupportedAppUsage
mCurrentInputMethodSession =
InputMethodSessionWrapper.createOrNull(res.method);
mCurId = res.id; mCurId = res.id;
mBindSequence = res.sequence; mBindSequence = res.sequence;
mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix(); mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
@@ -1004,7 +1018,7 @@ public final class InputMethodManager {
} }
mActivityViewToScreenMatrix.setValues(matrixValues); mActivityViewToScreenMatrix.setValues(matrixValues);
if (mCursorAnchorInfo == null || mCurMethod == null if (mCursorAnchorInfo == null || mCurrentInputMethodSession == null
|| mServedInputConnectionWrapper == null) { || mServedInputConnectionWrapper == null) {
return; return;
} }
@@ -1015,13 +1029,9 @@ public final class InputMethodManager {
} }
// Since the host ActivityView is moved, we need to issue // Since the host ActivityView is moved, we need to issue
// IMS#updateCursorAnchorInfo() again. // IMS#updateCursorAnchorInfo() again.
try { mCurrentInputMethodSession.updateCursorAnchorInfo(
mCurMethod.updateCursorAnchorInfo( CursorAnchorInfo.createForAdditionalParentMatrix(
CursorAnchorInfo.createForAdditionalParentMatrix( mCursorAnchorInfo, mActivityViewToScreenMatrix));
mCursorAnchorInfo, mActivityViewToScreenMatrix));
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
} }
return; return;
} }
@@ -1498,7 +1508,8 @@ public final class InputMethodManager {
setInputChannelLocked(null); setInputChannelLocked(null);
mBindSequence = -1; mBindSequence = -1;
mCurId = null; mCurId = null;
mCurMethod = null; mCurMethod = null; // for @UnsupportedAppUsage
mCurrentInputMethodSession = null;
} }
void setInputChannelLocked(InputChannel channel) { void setInputChannelLocked(InputChannel channel) {
@@ -1562,11 +1573,8 @@ public final class InputMethodManager {
} }
mCompletions = completions; mCompletions = completions;
if (mCurMethod != null) { if (mCurrentInputMethodSession != null) {
try { mCurrentInputMethodSession.displayCompletions(mCompletions);
mCurMethod.displayCompletions(mCompletions);
} catch (RemoteException e) {
}
} }
} }
} }
@@ -1585,11 +1593,8 @@ public final class InputMethodManager {
return; return;
} }
if (mCurMethod != null) { if (mCurrentInputMethodSession != null) {
try { mCurrentInputMethodSession.updateExtractedText(token, text);
mCurMethod.updateExtractedText(token, text);
} catch (RemoteException e) {
}
} }
} }
} }
@@ -1850,11 +1855,8 @@ public final class InputMethodManager {
if (servedView == null || servedView.getWindowToken() != windowToken) { if (servedView == null || servedView.getWindowToken() != windowToken) {
return; return;
} }
if (mCurMethod != null) { if (mCurrentInputMethodSession != null) {
try { mCurrentInputMethodSession.toggleSoftInput(showFlags, hideFlags);
mCurMethod.toggleSoftInput(showFlags, hideFlags);
} catch (RemoteException e) {
}
} }
} }
} }
@@ -1875,11 +1877,8 @@ public final class InputMethodManager {
ImeTracing.getInstance().triggerClientDump( ImeTracing.getInstance().triggerClientDump(
"InputMethodManager#toggleSoftInput", InputMethodManager.this, "InputMethodManager#toggleSoftInput", InputMethodManager.this,
null /* icProto */); null /* icProto */);
if (mCurMethod != null) { if (mCurrentInputMethodSession != null) {
try { mCurrentInputMethodSession.toggleSoftInput(showFlags, hideFlags);
mCurMethod.toggleSoftInput(showFlags, hideFlags);
} catch (RemoteException e) {
}
} }
} }
@@ -2062,7 +2061,8 @@ public final class InputMethodManager {
if (res.id != null) { if (res.id != null) {
setInputChannelLocked(res.channel); setInputChannelLocked(res.channel);
mBindSequence = res.sequence; mBindSequence = res.sequence;
mCurMethod = res.method; mCurMethod = res.method; // for @UnsupportedAppUsage
mCurrentInputMethodSession = InputMethodSessionWrapper.createOrNull(res.method);
mCurId = res.id; mCurId = res.id;
} else if (res.channel != null && res.channel != mCurChannel) { } else if (res.channel != null && res.channel != mCurChannel) {
res.channel.dispose(); res.channel.dispose();
@@ -2072,11 +2072,8 @@ public final class InputMethodManager {
mRestartOnNextWindowFocus = true; mRestartOnNextWindowFocus = true;
break; break;
} }
if (mCurMethod != null && mCompletions != null) { if (mCurrentInputMethodSession != null && mCompletions != null) {
try { mCurrentInputMethodSession.displayCompletions(mCompletions);
mCurMethod.displayCompletions(mCompletions);
} catch (RemoteException e) {
}
} }
} catch (RemoteException e) { } catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e); Log.w(TAG, "IME died: " + mCurId, e);
@@ -2234,12 +2231,9 @@ public final class InputMethodManager {
ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this, ImeTracing.getInstance().triggerClientDump("InputMethodManager#notifyImeHidden", this,
null /* icProto */); null /* icProto */);
synchronized (mH) { synchronized (mH) {
try { if (mCurrentInputMethodSession != null && mCurRootView != null
if (mCurMethod != null && mCurRootView != null && mCurRootView.getWindowToken() == windowToken) {
&& mCurRootView.getWindowToken() == windowToken) { mCurrentInputMethodSession.notifyImeHidden();
mCurMethod.notifyImeHidden();
}
} catch (RemoteException re) {
} }
} }
} }
@@ -2284,7 +2278,7 @@ public final class InputMethodManager {
checkFocus(); checkFocus();
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
|| mCurMethod == null) { || mCurrentInputMethodSession == null) {
return; return;
} }
@@ -2293,22 +2287,20 @@ public final class InputMethodManager {
|| mCursorCandEnd != candidatesEnd) { || mCursorCandEnd != candidatesEnd) {
if (DEBUG) Log.d(TAG, "updateSelection"); if (DEBUG) Log.d(TAG, "updateSelection");
try { if (DEBUG) {
if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod); Log.v(TAG, "SELECTION CHANGE: " + mCurrentInputMethodSession);
final int oldSelStart = mCursorSelStart;
final int oldSelEnd = mCursorSelEnd;
// Update internal values before sending updateSelection to the IME, because
// if it changes the text within its onUpdateSelection handler in a way that
// does not move the cursor we don't want to call it again with the same values.
mCursorSelStart = selStart;
mCursorSelEnd = selEnd;
mCursorCandStart = candidatesStart;
mCursorCandEnd = candidatesEnd;
mCurMethod.updateSelection(oldSelStart, oldSelEnd,
selStart, selEnd, candidatesStart, candidatesEnd);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
} }
final int oldSelStart = mCursorSelStart;
final int oldSelEnd = mCursorSelEnd;
// Update internal values before sending updateSelection to the IME, because
// if it changes the text within its onUpdateSelection handler in a way that
// does not move the cursor we don't want to call it again with the same values.
mCursorSelStart = selStart;
mCursorSelEnd = selEnd;
mCursorCandStart = candidatesStart;
mCursorCandEnd = candidatesEnd;
mCurrentInputMethodSession.updateSelection(
oldSelStart, oldSelEnd, selStart, selEnd, candidatesStart, candidatesEnd);
} }
} }
} }
@@ -2342,15 +2334,11 @@ public final class InputMethodManager {
checkFocus(); checkFocus();
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
|| mCurMethod == null) { || mCurrentInputMethodSession == null) {
return; return;
} }
try { if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged); mCurrentInputMethodSession.viewClicked(focusChanged);
mCurMethod.viewClicked(focusChanged);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
} }
} }
@@ -2411,21 +2399,16 @@ public final class InputMethodManager {
checkFocus(); checkFocus();
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
|| mCurMethod == null) { || mCurrentInputMethodSession == null) {
return; return;
} }
mTmpCursorRect.set(left, top, right, bottom); mTmpCursorRect.set(left, top, right, bottom);
if (!mCursorRect.equals(mTmpCursorRect)) { if (!mCursorRect.equals(mTmpCursorRect)) {
if (DEBUG) Log.d(TAG, "updateCursor"); if (DEBUG) Log.d(TAG, "updateCursor: " + mCurrentInputMethodSession);
try { mCurrentInputMethodSession.updateCursor(mTmpCursorRect);
if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod); mCursorRect.set(mTmpCursorRect);
mCurMethod.updateCursor(mTmpCursorRect);
mCursorRect.set(mTmpCursorRect);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
} }
} }
} }
@@ -2448,7 +2431,7 @@ public final class InputMethodManager {
checkFocus(); checkFocus();
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
|| mCurMethod == null) { || mCurrentInputMethodSession == null) {
return; return;
} }
// If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
@@ -2465,21 +2448,16 @@ public final class InputMethodManager {
return; return;
} }
if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo); if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
try { if (mActivityViewToScreenMatrix != null) {
if (mActivityViewToScreenMatrix != null) { mCurrentInputMethodSession.updateCursorAnchorInfo(
mCurMethod.updateCursorAnchorInfo( CursorAnchorInfo.createForAdditionalParentMatrix(
CursorAnchorInfo.createForAdditionalParentMatrix( cursorAnchorInfo, mActivityViewToScreenMatrix));
cursorAnchorInfo, mActivityViewToScreenMatrix)); } else {
} else { mCurrentInputMethodSession.updateCursorAnchorInfo(cursorAnchorInfo);
mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
}
mCursorAnchorInfo = cursorAnchorInfo;
// Clear immediate bit (if any).
mRequestUpdateCursorAnchorInfoMonitorMode &=
~InputConnection.CURSOR_UPDATE_IMMEDIATE;
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
} }
mCursorAnchorInfo = cursorAnchorInfo;
// Clear immediate bit (if any).
mRequestUpdateCursorAnchorInfoMonitorMode &= ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
} }
} }
@@ -2505,15 +2483,11 @@ public final class InputMethodManager {
checkFocus(); checkFocus();
synchronized (mH) { synchronized (mH) {
if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
|| mCurMethod == null) { || mCurrentInputMethodSession == null) {
return; return;
} }
try { if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data); mCurrentInputMethodSession.appPrivateCommand(action, data);
mCurMethod.appPrivateCommand(action, data);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
} }
} }
@@ -2671,7 +2645,7 @@ public final class InputMethodManager {
public int dispatchInputEvent(InputEvent event, Object token, public int dispatchInputEvent(InputEvent event, Object token,
FinishedInputEventCallback callback, Handler handler) { FinishedInputEventCallback callback, Handler handler) {
synchronized (mH) { synchronized (mH) {
if (mCurMethod != null) { if (mCurrentInputMethodSession != null) {
if (event instanceof KeyEvent) { if (event instanceof KeyEvent) {
KeyEvent keyEvent = (KeyEvent)event; KeyEvent keyEvent = (KeyEvent)event;
if (keyEvent.getAction() == KeyEvent.ACTION_DOWN if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
@@ -2682,7 +2656,9 @@ public final class InputMethodManager {
} }
} }
if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod); if (DEBUG) {
Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurrentInputMethodSession);
}
PendingEvent p = obtainPendingEventLocked( PendingEvent p = obtainPendingEventLocked(
event, token, mCurId, callback, handler); event, token, mCurId, callback, handler);
@@ -2772,8 +2748,7 @@ public final class InputMethodManager {
return DISPATCH_IN_PROGRESS; return DISPATCH_IN_PROGRESS;
} }
Log.w(TAG, "Unable to send input event to IME: " Log.w(TAG, "Unable to send input event to IME: " + mCurId + " dropping: " + event);
+ mCurId + " dropping: " + event);
} }
return DISPATCH_NOT_HANDLED; return DISPATCH_NOT_HANDLED;
} }
@@ -3230,7 +3205,11 @@ public final class InputMethodManager {
+ " mBindSequence=" + mBindSequence + " mBindSequence=" + mBindSequence
+ " mCurId=" + mCurId); + " mCurId=" + mCurId);
p.println(" mFullscreenMode=" + mFullscreenMode); p.println(" mFullscreenMode=" + mFullscreenMode);
p.println(" mCurMethod=" + mCurMethod); if (mCurrentInputMethodSession != null) {
p.println(" mCurMethod=" + mCurrentInputMethodSession);
} else {
p.println(" mCurMethod= null");
}
p.println(" mCurRootView=" + mCurRootView); p.println(" mCurRootView=" + mCurRootView);
p.println(" mServedView=" + getServedViewLocked()); p.println(" mServedView=" + getServedViewLocked());
p.println(" mNextServedView=" + getNextServedViewLocked()); p.println(" mNextServedView=" + getNextServedViewLocked());
@@ -3346,7 +3325,7 @@ public final class InputMethodManager {
*/ */
@GuardedBy("mH") @GuardedBy("mH")
public void dumpDebug(ProtoOutputStream proto, ProtoOutputStream icProto) { public void dumpDebug(ProtoOutputStream proto, ProtoOutputStream icProto) {
if (mCurMethod == null) { if (mCurrentInputMethodSession == null) {
return; return;
} }

View File

@@ -0,0 +1,163 @@
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.view.inputmethod;
import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import com.android.internal.view.IInputMethodSession;
/**
* This class wrap the {@link IInputMethodSession} object from {@link InputMethodManager}.
* Using current {@link IInputMethodSession} object to communicate with
* {@link android.inputmethodservice.InputMethodService}.
*/
final class InputMethodSessionWrapper {
private static final String TAG = "InputMethodSessionWrapper";
/**
* The actual instance of the method to make calls on it.
*/
@NonNull
private final IInputMethodSession mSession;
private InputMethodSessionWrapper(@NonNull IInputMethodSession inputMethodSession) {
mSession = inputMethodSession;
}
/**
* Create a {@link InputMethodSessionWrapper} instance if applicability.
*
* @param inputMethodSession {@link IInputMethodSession} object to be wrapped.
* @return an instance of {@link InputMethodSessionWrapper} if {@code inputMethodSession} is not
* {@code null}. {@code null} otherwise.
*/
@Nullable
public static InputMethodSessionWrapper createOrNull(
@NonNull IInputMethodSession inputMethodSession) {
return inputMethodSession != null ? new InputMethodSessionWrapper(inputMethodSession)
: null;
}
@AnyThread
void finishInput() {
try {
mSession.finishInput();
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void updateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
try {
mSession.updateCursorAnchorInfo(cursorAnchorInfo);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void displayCompletions(CompletionInfo[] completions) {
try {
mSession.displayCompletions(completions);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void updateExtractedText(int token, ExtractedText text) {
try {
mSession.updateExtractedText(token, text);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void toggleSoftInput(int showFlags, int hideFlags) {
try {
mSession.toggleSoftInput(showFlags, hideFlags);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void appPrivateCommand(String action, Bundle data) {
try {
mSession.appPrivateCommand(action, data);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void notifyImeHidden() {
try {
mSession.notifyImeHidden();
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void viewClicked(boolean focusChanged) {
try {
mSession.viewClicked(focusChanged);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void updateCursor(Rect newCursor) {
try {
mSession.updateCursor(newCursor);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
@AnyThread
void updateSelection(int oldSelStart, int oldSelEnd, int selStart, int selEnd,
int candidatesStart, int candidatesEnd) {
try {
mSession.updateSelection(
oldSelStart, oldSelEnd, selStart, selEnd, candidatesStart, candidatesEnd);
} catch (RemoteException e) {
Log.w(TAG, "IME died", e);
}
}
/**
* @return {@link IInputMethodSession#toString()} as a debug string.
*/
@AnyThread
@NonNull
@Override
public String toString() {
return mSession.toString();
}
}