Merge "Make sure to call back reportFinish() on the desired Handler." into nyc-dev
This commit is contained in:
@@ -3287,7 +3287,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
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_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_CLOSE_SYSTEM_DIALOGS = 14;
|
||||
private final static int MSG_DISPATCH_DRAG_EVENT = 15;
|
||||
@@ -3327,8 +3326,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
return "MSG_DISPATCH_GET_NEW_SURFACE";
|
||||
case 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:
|
||||
return "MSG_CHECK_FOCUS";
|
||||
case MSG_CLOSE_SYSTEM_DIALOGS:
|
||||
@@ -3549,12 +3546,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
|
||||
} break;
|
||||
case MSG_FINISH_INPUT_CONNECTION: {
|
||||
InputMethodManager imm = InputMethodManager.peekInstance();
|
||||
if (imm != null) {
|
||||
imm.reportFinishInputConnection((InputConnection)msg.obj);
|
||||
}
|
||||
} break;
|
||||
case MSG_CHECK_FOCUS: {
|
||||
InputMethodManager imm = InputMethodManager.peekInstance();
|
||||
if (imm != null) {
|
||||
@@ -5864,11 +5855,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,
|
||||
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
|
||||
Configuration newConfig, Rect backDropFrame, boolean forceLayout,
|
||||
|
||||
@@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
protected void reportFinish() {
|
||||
// Intentionaly empty
|
||||
public void reportFinish() {
|
||||
// Intentionally empty
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -531,22 +531,25 @@ public final class InputMethodManager {
|
||||
|
||||
private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
|
||||
private final InputMethodManager mParentInputMethodManager;
|
||||
private boolean mActive;
|
||||
|
||||
public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
|
||||
final InputMethodManager inputMethodManager) {
|
||||
super(mainLooper, conn);
|
||||
mParentInputMethodManager = inputMethodManager;
|
||||
mActive = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return mParentInputMethodManager.mActive && mActive;
|
||||
return mParentInputMethodManager.mActive && !isFinished();
|
||||
}
|
||||
|
||||
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
|
||||
@@ -563,7 +566,7 @@ public final class InputMethodManager {
|
||||
public String toString() {
|
||||
return "ControlledInputConnectionWrapper{"
|
||||
+ "connection=" + getInputConnection()
|
||||
+ " mActive=" + mActive
|
||||
+ " finished=" + isFinished()
|
||||
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
|
||||
+ "}";
|
||||
}
|
||||
@@ -837,7 +840,6 @@ public final class InputMethodManager {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
notifyInputConnectionFinished();
|
||||
mServedView = null;
|
||||
mCompletions = null;
|
||||
mServedConnecting = false;
|
||||
@@ -845,48 +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 || mServedInputConnectionWrapper == null) {
|
||||
return;
|
||||
}
|
||||
final InputConnection inputConnection = mServedInputConnectionWrapper.getInputConnection();
|
||||
if (inputConnection == null) {
|
||||
return;
|
||||
}
|
||||
// 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(inputConnection);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the FINISH_INPUT_CONNECTION message above.
|
||||
* @hide
|
||||
*/
|
||||
public void reportFinishInputConnection(InputConnection ic) {
|
||||
final InputConnection currentConnection;
|
||||
if (mServedInputConnectionWrapper == null) {
|
||||
currentConnection = null;
|
||||
} else {
|
||||
currentConnection = mServedInputConnectionWrapper.getInputConnection();
|
||||
}
|
||||
if (currentConnection != ic) {
|
||||
ic.finishComposingText();
|
||||
// To avoid modifying the public InputConnection interface
|
||||
if (ic instanceof BaseInputConnection) {
|
||||
((BaseInputConnection) ic).reportFinish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void displayCompletions(View view, CompletionInfo[] completions) {
|
||||
checkFocus();
|
||||
synchronized (mH) {
|
||||
@@ -1252,8 +1212,10 @@ public final class InputMethodManager {
|
||||
// Hook 'em up and let 'er rip.
|
||||
mCurrentTextBoxAttribute = tba;
|
||||
mServedConnecting = false;
|
||||
// Notify the served view that its previous input connection is finished
|
||||
notifyInputConnectionFinished();
|
||||
if (mServedInputConnectionWrapper != null) {
|
||||
mServedInputConnectionWrapper.deactivate();
|
||||
mServedInputConnectionWrapper = null;
|
||||
}
|
||||
ControlledInputConnectionWrapper servedContext;
|
||||
final int missingMethodFlags;
|
||||
if (ic != null) {
|
||||
@@ -1278,9 +1240,6 @@ public final class InputMethodManager {
|
||||
servedContext = null;
|
||||
missingMethodFlags = 0;
|
||||
}
|
||||
if (mServedInputConnectionWrapper != null) {
|
||||
mServedInputConnectionWrapper.deactivate();
|
||||
}
|
||||
mServedInputConnectionWrapper = servedContext;
|
||||
|
||||
try {
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.internal.view;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Bundle;
|
||||
@@ -25,6 +27,7 @@ import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
import android.view.inputmethod.CorrectionInfo;
|
||||
import android.view.inputmethod.ExtractedTextRequest;
|
||||
@@ -58,12 +61,16 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
|
||||
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_REPORT_FINISH = 150;
|
||||
|
||||
@NonNull
|
||||
private final WeakReference<InputConnection> mInputConnection;
|
||||
|
||||
private Looper mMainLooper;
|
||||
private Handler mH;
|
||||
private Object mLock = new Object();
|
||||
@GuardedBy("mLock")
|
||||
private boolean mFinished = false;
|
||||
|
||||
static class SomeArgs {
|
||||
Object arg1;
|
||||
@@ -94,6 +101,12 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
return mInputConnection.get();
|
||||
}
|
||||
|
||||
protected boolean isFinished() {
|
||||
synchronized (mLock) {
|
||||
return mFinished;
|
||||
}
|
||||
}
|
||||
|
||||
abstract protected boolean isActive();
|
||||
|
||||
/**
|
||||
@@ -206,6 +219,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
seq, callback));
|
||||
}
|
||||
|
||||
public void reportFinish() {
|
||||
dispatchMessage(obtainMessage(DO_REPORT_FINISH));
|
||||
}
|
||||
|
||||
void dispatchMessage(Message msg) {
|
||||
// If we are calling this from the main thread, then we can call
|
||||
// right through. Otherwise, we need to send the message to the
|
||||
@@ -218,7 +235,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
|
||||
mH.sendMessage(msg);
|
||||
}
|
||||
|
||||
|
||||
void executeMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case DO_GET_TEXT_AFTER_CURSOR: {
|
||||
@@ -481,6 +498,36 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
|
||||
}
|
||||
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 = mInputConnection.get();
|
||||
// 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) {
|
||||
mFinished = true;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
Log.w(TAG, "Unhandled message code: " + msg.what);
|
||||
}
|
||||
|
||||
@@ -83,8 +83,11 @@ public class EditableInputConnection extends BaseInputConnection {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
@Override
|
||||
protected void reportFinish() {
|
||||
public void reportFinish() {
|
||||
super.reportFinish();
|
||||
|
||||
synchronized(this) {
|
||||
|
||||
Reference in New Issue
Block a user