Merge "Ensure IC#finishComposingText() is called on the correct Handler." into nyc-dev
am: 9194f34
* commit '9194f344b922cd04e5e44206ada6191865631daa':
Ensure IC#finishComposingText() is called on the correct Handler.
This commit is contained in:
@@ -3300,7 +3300,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
|
private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
|
||||||
private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
|
private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
|
||||||
private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
|
private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
|
||||||
private final static int MSG_FINISH_INPUT_CONNECTION = 12;
|
|
||||||
private final static int MSG_CHECK_FOCUS = 13;
|
private final static int MSG_CHECK_FOCUS = 13;
|
||||||
private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
|
private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
|
||||||
private final static int MSG_DISPATCH_DRAG_EVENT = 15;
|
private final static int MSG_DISPATCH_DRAG_EVENT = 15;
|
||||||
@@ -3340,8 +3339,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
return "MSG_DISPATCH_GET_NEW_SURFACE";
|
return "MSG_DISPATCH_GET_NEW_SURFACE";
|
||||||
case MSG_DISPATCH_KEY_FROM_IME:
|
case MSG_DISPATCH_KEY_FROM_IME:
|
||||||
return "MSG_DISPATCH_KEY_FROM_IME";
|
return "MSG_DISPATCH_KEY_FROM_IME";
|
||||||
case MSG_FINISH_INPUT_CONNECTION:
|
|
||||||
return "MSG_FINISH_INPUT_CONNECTION";
|
|
||||||
case MSG_CHECK_FOCUS:
|
case MSG_CHECK_FOCUS:
|
||||||
return "MSG_CHECK_FOCUS";
|
return "MSG_CHECK_FOCUS";
|
||||||
case MSG_CLOSE_SYSTEM_DIALOGS:
|
case MSG_CLOSE_SYSTEM_DIALOGS:
|
||||||
@@ -3562,12 +3559,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
|
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
|
||||||
} break;
|
} break;
|
||||||
case MSG_FINISH_INPUT_CONNECTION: {
|
|
||||||
InputMethodManager imm = InputMethodManager.peekInstance();
|
|
||||||
if (imm != null) {
|
|
||||||
imm.reportFinishInputConnection((InputConnection)msg.obj);
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
case MSG_CHECK_FOCUS: {
|
case MSG_CHECK_FOCUS: {
|
||||||
InputMethodManager imm = InputMethodManager.peekInstance();
|
InputMethodManager imm = InputMethodManager.peekInstance();
|
||||||
if (imm != null) {
|
if (imm != null) {
|
||||||
@@ -5878,11 +5869,6 @@ public final class ViewRootImpl implements ViewParent,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dispatchFinishInputConnection(InputConnection connection) {
|
|
||||||
Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection);
|
|
||||||
mHandler.sendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
|
public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
|
||||||
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
|
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
|
||||||
Configuration newConfig, Rect backDropFrame, boolean forceLayout,
|
Configuration newConfig, Rect backDropFrame, boolean forceLayout,
|
||||||
|
|||||||
@@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection {
|
|||||||
*
|
*
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
protected void reportFinish() {
|
public void reportFinish() {
|
||||||
// Intentionaly empty
|
// Intentionally empty
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -317,7 +317,6 @@ public final class InputMethodManager {
|
|||||||
/**
|
/**
|
||||||
* The InputConnection that was last retrieved from the served view.
|
* The InputConnection that was last retrieved from the served view.
|
||||||
*/
|
*/
|
||||||
InputConnection mServedInputConnection;
|
|
||||||
ControlledInputConnectionWrapper mServedInputConnectionWrapper;
|
ControlledInputConnectionWrapper mServedInputConnectionWrapper;
|
||||||
/**
|
/**
|
||||||
* The completions that were last provided by the served view.
|
* The completions that were last provided by the served view.
|
||||||
@@ -498,7 +497,7 @@ public final class InputMethodManager {
|
|||||||
// from a thread that created mServedView. That could happen
|
// from a thread that created mServedView. That could happen
|
||||||
// the current activity is running in the system process.
|
// the current activity is running in the system process.
|
||||||
// In that case, we really should not call
|
// In that case, we really should not call
|
||||||
// mServedInputConnection.finishComposingText.
|
// mServedInputConnectionWrapper.finishComposingText().
|
||||||
if (checkFocusNoStartInput(mHasBeenInactive, false)) {
|
if (checkFocusNoStartInput(mHasBeenInactive, false)) {
|
||||||
final int reason = active ?
|
final int reason = active ?
|
||||||
InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS :
|
InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS :
|
||||||
@@ -532,22 +531,25 @@ 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 boolean mActive;
|
|
||||||
|
|
||||||
public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
|
public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
|
||||||
final InputMethodManager inputMethodManager) {
|
final InputMethodManager inputMethodManager) {
|
||||||
super(mainLooper, conn);
|
super(mainLooper, conn);
|
||||||
mParentInputMethodManager = inputMethodManager;
|
mParentInputMethodManager = inputMethodManager;
|
||||||
mActive = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isActive() {
|
public boolean isActive() {
|
||||||
return mParentInputMethodManager.mActive && mActive;
|
return mParentInputMethodManager.mActive && !isFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
void deactivate() {
|
void deactivate() {
|
||||||
mActive = false;
|
if (isFinished()) {
|
||||||
|
// This is a small performance optimization. Still only the 1st call of
|
||||||
|
// reportFinish() will take effect.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reportFinish();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -562,7 +564,9 @@ public final class InputMethodManager {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "ControlledInputConnectionWrapper{mActive=" + mActive
|
return "ControlledInputConnectionWrapper{"
|
||||||
|
+ "connection=" + getInputConnection()
|
||||||
|
+ " finished=" + isFinished()
|
||||||
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
|
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
|
||||||
+ "}";
|
+ "}";
|
||||||
}
|
}
|
||||||
@@ -780,7 +784,8 @@ public final class InputMethodManager {
|
|||||||
*/
|
*/
|
||||||
public boolean isAcceptingText() {
|
public boolean isAcceptingText() {
|
||||||
checkFocus();
|
checkFocus();
|
||||||
return mServedInputConnection != null;
|
return mServedInputConnectionWrapper != null &&
|
||||||
|
mServedInputConnectionWrapper.getInputConnection() != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -815,7 +820,6 @@ public final class InputMethodManager {
|
|||||||
*/
|
*/
|
||||||
void clearConnectionLocked() {
|
void clearConnectionLocked() {
|
||||||
mCurrentTextBoxAttribute = null;
|
mCurrentTextBoxAttribute = null;
|
||||||
mServedInputConnection = null;
|
|
||||||
if (mServedInputConnectionWrapper != null) {
|
if (mServedInputConnectionWrapper != null) {
|
||||||
mServedInputConnectionWrapper.deactivate();
|
mServedInputConnectionWrapper.deactivate();
|
||||||
mServedInputConnectionWrapper = null;
|
mServedInputConnectionWrapper = null;
|
||||||
@@ -836,7 +840,6 @@ public final class InputMethodManager {
|
|||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notifyInputConnectionFinished();
|
|
||||||
mServedView = null;
|
mServedView = null;
|
||||||
mCompletions = null;
|
mCompletions = null;
|
||||||
mServedConnecting = false;
|
mServedConnecting = false;
|
||||||
@@ -844,37 +847,6 @@ public final class InputMethodManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notifies the served view that the current InputConnection will no longer be used.
|
|
||||||
*/
|
|
||||||
private void notifyInputConnectionFinished() {
|
|
||||||
if (mServedView != null && mServedInputConnection != null) {
|
|
||||||
// We need to tell the previously served view that it is no
|
|
||||||
// longer the input target, so it can reset its state. Schedule
|
|
||||||
// this call on its window's Handler so it will be on the correct
|
|
||||||
// thread and outside of our lock.
|
|
||||||
ViewRootImpl viewRootImpl = mServedView.getViewRootImpl();
|
|
||||||
if (viewRootImpl != null) {
|
|
||||||
// This will result in a call to reportFinishInputConnection() below.
|
|
||||||
viewRootImpl.dispatchFinishInputConnection(mServedInputConnection);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called from the FINISH_INPUT_CONNECTION message above.
|
|
||||||
* @hide
|
|
||||||
*/
|
|
||||||
public void reportFinishInputConnection(InputConnection ic) {
|
|
||||||
if (mServedInputConnection != ic) {
|
|
||||||
ic.finishComposingText();
|
|
||||||
// To avoid modifying the public InputConnection interface
|
|
||||||
if (ic instanceof BaseInputConnection) {
|
|
||||||
((BaseInputConnection) ic).reportFinish();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void displayCompletions(View view, CompletionInfo[] completions) {
|
public void displayCompletions(View view, CompletionInfo[] completions) {
|
||||||
checkFocus();
|
checkFocus();
|
||||||
synchronized (mH) {
|
synchronized (mH) {
|
||||||
@@ -1240,9 +1212,10 @@ public final class InputMethodManager {
|
|||||||
// Hook 'em up and let 'er rip.
|
// Hook 'em up and let 'er rip.
|
||||||
mCurrentTextBoxAttribute = tba;
|
mCurrentTextBoxAttribute = tba;
|
||||||
mServedConnecting = false;
|
mServedConnecting = false;
|
||||||
// Notify the served view that its previous input connection is finished
|
if (mServedInputConnectionWrapper != null) {
|
||||||
notifyInputConnectionFinished();
|
mServedInputConnectionWrapper.deactivate();
|
||||||
mServedInputConnection = ic;
|
mServedInputConnectionWrapper = null;
|
||||||
|
}
|
||||||
ControlledInputConnectionWrapper servedContext;
|
ControlledInputConnectionWrapper servedContext;
|
||||||
final int missingMethodFlags;
|
final int missingMethodFlags;
|
||||||
if (ic != null) {
|
if (ic != null) {
|
||||||
@@ -1267,9 +1240,6 @@ public final class InputMethodManager {
|
|||||||
servedContext = null;
|
servedContext = null;
|
||||||
missingMethodFlags = 0;
|
missingMethodFlags = 0;
|
||||||
}
|
}
|
||||||
if (mServedInputConnectionWrapper != null) {
|
|
||||||
mServedInputConnectionWrapper.deactivate();
|
|
||||||
}
|
|
||||||
mServedInputConnectionWrapper = servedContext;
|
mServedInputConnectionWrapper = servedContext;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -1413,7 +1383,7 @@ public final class InputMethodManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputConnection ic = null;
|
final ControlledInputConnectionWrapper ic;
|
||||||
synchronized (mH) {
|
synchronized (mH) {
|
||||||
if (mServedView == mNextServedView && !forceNewFocus) {
|
if (mServedView == mNextServedView && !forceNewFocus) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1433,7 +1403,7 @@ public final class InputMethodManager {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ic = mServedInputConnection;
|
ic = mServedInputConnectionWrapper;
|
||||||
|
|
||||||
mServedView = mNextServedView;
|
mServedView = mNextServedView;
|
||||||
mCurrentTextBoxAttribute = null;
|
mCurrentTextBoxAttribute = null;
|
||||||
@@ -2282,7 +2252,7 @@ public final class InputMethodManager {
|
|||||||
} else {
|
} else {
|
||||||
p.println(" mCurrentTextBoxAttribute: null");
|
p.println(" mCurrentTextBoxAttribute: null");
|
||||||
}
|
}
|
||||||
p.println(" mServedInputConnection=" + mServedInputConnection);
|
p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
|
||||||
p.println(" mCompletions=" + Arrays.toString(mCompletions));
|
p.println(" mCompletions=" + Arrays.toString(mCompletions));
|
||||||
p.println(" mCursorRect=" + mCursorRect);
|
p.println(" mCursorRect=" + mCursorRect);
|
||||||
p.println(" mCursorSelStart=" + mCursorSelStart
|
p.println(" mCursorSelStart=" + mCursorSelStart
|
||||||
|
|||||||
@@ -16,6 +16,10 @@
|
|||||||
|
|
||||||
package com.android.internal.view;
|
package com.android.internal.view;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
@@ -23,6 +27,7 @@ import android.os.Message;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
|
import android.view.inputmethod.BaseInputConnection;
|
||||||
import android.view.inputmethod.CompletionInfo;
|
import android.view.inputmethod.CompletionInfo;
|
||||||
import android.view.inputmethod.CorrectionInfo;
|
import android.view.inputmethod.CorrectionInfo;
|
||||||
import android.view.inputmethod.ExtractedTextRequest;
|
import android.view.inputmethod.ExtractedTextRequest;
|
||||||
@@ -56,11 +61,17 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
|
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
|
||||||
private static final int DO_CLEAR_META_KEY_STATES = 130;
|
private static final int DO_CLEAR_META_KEY_STATES = 130;
|
||||||
private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
|
private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
|
||||||
|
private static final int DO_REPORT_FINISH = 150;
|
||||||
|
|
||||||
private WeakReference<InputConnection> mInputConnection;
|
@GuardedBy("mLock")
|
||||||
|
@Nullable
|
||||||
|
private InputConnection mInputConnection;
|
||||||
|
|
||||||
private Looper mMainLooper;
|
private Looper mMainLooper;
|
||||||
private Handler mH;
|
private Handler mH;
|
||||||
|
private Object mLock = new Object();
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private boolean mFinished = false;
|
||||||
|
|
||||||
static class SomeArgs {
|
static class SomeArgs {
|
||||||
Object arg1;
|
Object arg1;
|
||||||
@@ -80,12 +91,25 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IInputConnectionWrapper(Looper mainLooper, InputConnection conn) {
|
public IInputConnectionWrapper(Looper mainLooper, @NonNull InputConnection inputConnection) {
|
||||||
mInputConnection = new WeakReference<>(conn);
|
mInputConnection = inputConnection;
|
||||||
mMainLooper = mainLooper;
|
mMainLooper = mainLooper;
|
||||||
mH = new MyHandler(mMainLooper);
|
mH = new MyHandler(mMainLooper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public InputConnection getInputConnection() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
return mInputConnection;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isFinished() {
|
||||||
|
synchronized (mLock) {
|
||||||
|
return mFinished;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
abstract protected boolean isActive();
|
abstract protected boolean isActive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,6 +222,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
seq, callback));
|
seq, callback));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void reportFinish() {
|
||||||
|
dispatchMessage(obtainMessage(DO_REPORT_FINISH));
|
||||||
|
}
|
||||||
|
|
||||||
void dispatchMessage(Message msg) {
|
void dispatchMessage(Message msg) {
|
||||||
// If we are calling this from the main thread, then we can call
|
// If we are calling this from the main thread, then we can call
|
||||||
// right through. Otherwise, we need to send the message to the
|
// right through. Otherwise, we need to send the message to the
|
||||||
@@ -210,13 +238,13 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
|
|
||||||
mH.sendMessage(msg);
|
mH.sendMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void executeMessage(Message msg) {
|
void executeMessage(Message msg) {
|
||||||
switch (msg.what) {
|
switch (msg.what) {
|
||||||
case DO_GET_TEXT_AFTER_CURSOR: {
|
case DO_GET_TEXT_AFTER_CURSOR: {
|
||||||
SomeArgs args = (SomeArgs)msg.obj;
|
SomeArgs args = (SomeArgs)msg.obj;
|
||||||
try {
|
try {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
|
Log.w(TAG, "getTextAfterCursor on inactive InputConnection");
|
||||||
args.callback.setTextAfterCursor(null, args.seq);
|
args.callback.setTextAfterCursor(null, args.seq);
|
||||||
@@ -232,7 +260,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
case DO_GET_TEXT_BEFORE_CURSOR: {
|
case DO_GET_TEXT_BEFORE_CURSOR: {
|
||||||
SomeArgs args = (SomeArgs)msg.obj;
|
SomeArgs args = (SomeArgs)msg.obj;
|
||||||
try {
|
try {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
|
Log.w(TAG, "getTextBeforeCursor on inactive InputConnection");
|
||||||
args.callback.setTextBeforeCursor(null, args.seq);
|
args.callback.setTextBeforeCursor(null, args.seq);
|
||||||
@@ -248,7 +276,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
case DO_GET_SELECTED_TEXT: {
|
case DO_GET_SELECTED_TEXT: {
|
||||||
SomeArgs args = (SomeArgs)msg.obj;
|
SomeArgs args = (SomeArgs)msg.obj;
|
||||||
try {
|
try {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "getSelectedText on inactive InputConnection");
|
Log.w(TAG, "getSelectedText on inactive InputConnection");
|
||||||
args.callback.setSelectedText(null, args.seq);
|
args.callback.setSelectedText(null, args.seq);
|
||||||
@@ -264,7 +292,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
case DO_GET_CURSOR_CAPS_MODE: {
|
case DO_GET_CURSOR_CAPS_MODE: {
|
||||||
SomeArgs args = (SomeArgs)msg.obj;
|
SomeArgs args = (SomeArgs)msg.obj;
|
||||||
try {
|
try {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
|
Log.w(TAG, "getCursorCapsMode on inactive InputConnection");
|
||||||
args.callback.setCursorCapsMode(0, args.seq);
|
args.callback.setCursorCapsMode(0, args.seq);
|
||||||
@@ -280,7 +308,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
case DO_GET_EXTRACTED_TEXT: {
|
case DO_GET_EXTRACTED_TEXT: {
|
||||||
SomeArgs args = (SomeArgs)msg.obj;
|
SomeArgs args = (SomeArgs)msg.obj;
|
||||||
try {
|
try {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "getExtractedText on inactive InputConnection");
|
Log.w(TAG, "getExtractedText on inactive InputConnection");
|
||||||
args.callback.setExtractedText(null, args.seq);
|
args.callback.setExtractedText(null, args.seq);
|
||||||
@@ -294,7 +322,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_COMMIT_TEXT: {
|
case DO_COMMIT_TEXT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "commitText on inactive InputConnection");
|
Log.w(TAG, "commitText on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -304,7 +332,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_SET_SELECTION: {
|
case DO_SET_SELECTION: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "setSelection on inactive InputConnection");
|
Log.w(TAG, "setSelection on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -313,7 +341,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_PERFORM_EDITOR_ACTION: {
|
case DO_PERFORM_EDITOR_ACTION: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "performEditorAction on inactive InputConnection");
|
Log.w(TAG, "performEditorAction on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -322,7 +350,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_PERFORM_CONTEXT_MENU_ACTION: {
|
case DO_PERFORM_CONTEXT_MENU_ACTION: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "performContextMenuAction on inactive InputConnection");
|
Log.w(TAG, "performContextMenuAction on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -331,7 +359,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_COMMIT_COMPLETION: {
|
case DO_COMMIT_COMPLETION: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "commitCompletion on inactive InputConnection");
|
Log.w(TAG, "commitCompletion on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -340,7 +368,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_COMMIT_CORRECTION: {
|
case DO_COMMIT_CORRECTION: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "commitCorrection on inactive InputConnection");
|
Log.w(TAG, "commitCorrection on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -349,7 +377,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_SET_COMPOSING_TEXT: {
|
case DO_SET_COMPOSING_TEXT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "setComposingText on inactive InputConnection");
|
Log.w(TAG, "setComposingText on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -359,7 +387,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_SET_COMPOSING_REGION: {
|
case DO_SET_COMPOSING_REGION: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "setComposingRegion on inactive InputConnection");
|
Log.w(TAG, "setComposingRegion on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -368,7 +396,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_FINISH_COMPOSING_TEXT: {
|
case DO_FINISH_COMPOSING_TEXT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
// Note we do NOT check isActive() here, because this is safe
|
// Note we do NOT check isActive() here, because this is safe
|
||||||
// for an IME to call at any time, and we need to allow it
|
// for an IME to call at any time, and we need to allow it
|
||||||
// through to clean up our state after the IME has switched to
|
// through to clean up our state after the IME has switched to
|
||||||
@@ -381,7 +409,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_SEND_KEY_EVENT: {
|
case DO_SEND_KEY_EVENT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "sendKeyEvent on inactive InputConnection");
|
Log.w(TAG, "sendKeyEvent on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -391,7 +419,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_CLEAR_META_KEY_STATES: {
|
case DO_CLEAR_META_KEY_STATES: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
|
Log.w(TAG, "clearMetaKeyStates on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -400,7 +428,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_DELETE_SURROUNDING_TEXT: {
|
case DO_DELETE_SURROUNDING_TEXT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
|
Log.w(TAG, "deleteSurroundingText on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -409,7 +437,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: {
|
case DO_DELETE_SURROUNDING_TEXT_IN_CODE_POINTS: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
|
Log.w(TAG, "deleteSurroundingTextInCodePoints on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -418,7 +446,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_BEGIN_BATCH_EDIT: {
|
case DO_BEGIN_BATCH_EDIT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "beginBatchEdit on inactive InputConnection");
|
Log.w(TAG, "beginBatchEdit on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -427,7 +455,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_END_BATCH_EDIT: {
|
case DO_END_BATCH_EDIT: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "endBatchEdit on inactive InputConnection");
|
Log.w(TAG, "endBatchEdit on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -436,7 +464,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_REPORT_FULLSCREEN_MODE: {
|
case DO_REPORT_FULLSCREEN_MODE: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null) {
|
if (ic == null) {
|
||||||
Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
|
Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -447,7 +475,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case DO_PERFORM_PRIVATE_COMMAND: {
|
case DO_PERFORM_PRIVATE_COMMAND: {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "performPrivateCommand on inactive InputConnection");
|
Log.w(TAG, "performPrivateCommand on inactive InputConnection");
|
||||||
return;
|
return;
|
||||||
@@ -460,7 +488,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
|
case DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO: {
|
||||||
SomeArgs args = (SomeArgs)msg.obj;
|
SomeArgs args = (SomeArgs)msg.obj;
|
||||||
try {
|
try {
|
||||||
InputConnection ic = mInputConnection.get();
|
InputConnection ic = getInputConnection();
|
||||||
if (ic == null || !isActive()) {
|
if (ic == null || !isActive()) {
|
||||||
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
|
Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
|
||||||
args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq);
|
args.callback.setRequestUpdateCursorAnchorInfoResult(false, args.seq);
|
||||||
@@ -473,6 +501,37 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
case DO_REPORT_FINISH: {
|
||||||
|
// Note that we do not need to worry about race condition here, because 1) mFinished
|
||||||
|
// is updated only inside this block, and 2) the code here is running on a Handler
|
||||||
|
// hence we assume multiple DO_REPORT_FINISH messages will not be handled at the
|
||||||
|
// same time.
|
||||||
|
if (isFinished()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
InputConnection ic = getInputConnection();
|
||||||
|
// Note we do NOT check isActive() here, because this is safe
|
||||||
|
// for an IME to call at any time, and we need to allow it
|
||||||
|
// through to clean up our state after the IME has switched to
|
||||||
|
// another client.
|
||||||
|
if (ic == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ic.finishComposingText();
|
||||||
|
// TODO: Make reportFinish() public method of InputConnection to remove this
|
||||||
|
// check.
|
||||||
|
if (ic instanceof BaseInputConnection) {
|
||||||
|
((BaseInputConnection) ic).reportFinish();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
synchronized (mLock) {
|
||||||
|
mInputConnection = null;
|
||||||
|
mFinished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Log.w(TAG, "Unhandled message code: " + msg.what);
|
Log.w(TAG, "Unhandled message code: " + msg.what);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,8 +83,11 @@ public class EditableInputConnection extends BaseInputConnection {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void reportFinish() {
|
public void reportFinish() {
|
||||||
super.reportFinish();
|
super.reportFinish();
|
||||||
|
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
|
|||||||
Reference in New Issue
Block a user