BaseInputConnection shouldn't rely on @hide APIs.
This is a part of effort to reduce the number of dependencies on @hide
method in BaseInputConnection.
In a nutshell, IMM#notifyUserAction() and IMM#setFullscreenMode() are
something that IME developers should not care about, hence ideally
BaseInputConnection should not rely on them.
IMM#setFullscreenMode():
This @hide method is just for updating an internal state flag about
whether the current IME is in full screen mode or not.
IMM#notifyUserAction():
This @hide methods is just for sending a signal to IMMS so that IME
rotation list (for globe button) can be updated based on the user's
action.
Depending on those @hide methods in BaseInputConnection is problematic
because:
A. We cannot implement InputConnection without relying on
BaseInputConnection, which forces developers to use Editable to
maintain internal text representations.
B. If BaseInputConnection#commitText is overridden,
those @hide method calls can be missed.
C. Currently some method calls of BaseInputConnection() even from
application itself can trigger those @hide method calls. Ideally
those internal events can be dispatched only when those methods are
called from the input method rather than the application itself.
With this CL, those @hide API calls will be moved from
BaseInputConnection to ControlledInputConnectionWrapper so that
developers can forget about them.
Note that BaseInputConnection#sendKeyEvent() still relies on @hide
internal details of IMM. It should be addressed in a subsequent CL.
Bug: 24688781
Change-Id: I571d6cc9c6e461d8994aa7496e7e18be13766411
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index ba5d6c2..8cfb1ee 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -195,7 +195,6 @@
public boolean commitText(CharSequence text, int newCursorPosition) {
if (DEBUG) Log.v(TAG, "commitText " + text);
replaceText(text, newCursorPosition, false);
- mIMM.notifyUserAction();
sendCurrentText();
return true;
}
@@ -443,7 +442,6 @@
public boolean setComposingText(CharSequence text, int newCursorPosition) {
if (DEBUG) Log.v(TAG, "setComposingText " + text);
replaceText(text, newCursorPosition, true);
- mIMM.notifyUserAction();
return true;
}
@@ -527,18 +525,16 @@
viewRootImpl.dispatchKeyFromIme(event);
}
}
- mIMM.notifyUserAction();
return false;
}
-
+
/**
* Updates InputMethodManager with the current fullscreen mode.
*/
public boolean reportFullscreenMode(boolean enabled) {
- mIMM.setFullscreenMode(enabled);
return true;
}
-
+
private void sendCurrentText() {
if (!mDummyMode) {
return;
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 5e07347..15a5d20 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -527,7 +527,7 @@
}
}
}
-
+
private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
private final InputMethodManager mParentInputMethodManager;
private boolean mActive;
@@ -549,13 +549,23 @@
}
@Override
+ protected void onUserAction() {
+ mParentInputMethodManager.notifyUserAction();
+ }
+
+ @Override
+ protected void onReportFullscreenMode(boolean enabled) {
+ mParentInputMethodManager.setFullscreenMode(enabled);
+ }
+
+ @Override
public String toString() {
return "ControlledInputConnectionWrapper{mActive=" + mActive
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
+ "}";
}
}
-
+
final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
@Override
protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 85ec29c..0e7f06b 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -30,7 +30,7 @@
import java.lang.ref.WeakReference;
-public class IInputConnectionWrapper extends IInputContext.Stub {
+public abstract class IInputConnectionWrapper extends IInputContext.Stub {
static final String TAG = "IInputConnectionWrapper";
private static final int DO_GET_TEXT_AFTER_CURSOR = 10;
@@ -80,15 +80,25 @@
}
public IInputConnectionWrapper(Looper mainLooper, InputConnection conn) {
- mInputConnection = new WeakReference<InputConnection>(conn);
+ mInputConnection = new WeakReference<>(conn);
mMainLooper = mainLooper;
mH = new MyHandler(mMainLooper);
}
- public boolean isActive() {
- return true;
- }
-
+ abstract protected boolean isActive();
+
+ /**
+ * Called when the user took some actions that should be taken into consideration to update the
+ * LRU list for input method rotation.
+ */
+ abstract protected void onUserAction();
+
+ /**
+ * Called when the input method started or stopped full-screen mode.
+ *
+ */
+ abstract protected void onReportFullscreenMode(boolean enabled);
+
public void getTextAfterCursor(int length, int flags, int seq, IInputContextCallback callback) {
dispatchMessage(obtainMessageIISC(DO_GET_TEXT_AFTER_CURSOR, length, flags, seq, callback));
}
@@ -284,6 +294,7 @@
return;
}
ic.commitText((CharSequence)msg.obj, msg.arg1);
+ onUserAction();
return;
}
case DO_SET_SELECTION: {
@@ -338,6 +349,7 @@
return;
}
ic.setComposingText((CharSequence)msg.obj, msg.arg1);
+ onUserAction();
return;
}
case DO_SET_COMPOSING_REGION: {
@@ -369,6 +381,7 @@
return;
}
ic.sendKeyEvent((KeyEvent)msg.obj);
+ onUserAction();
return;
}
case DO_CLEAR_META_KEY_STATES: {
@@ -413,7 +426,9 @@
Log.w(TAG, "reportFullscreenMode on inexistent InputConnection");
return;
}
- ic.reportFullscreenMode(msg.arg1 == 1);
+ final boolean enabled = msg.arg1 == 1;
+ ic.reportFullscreenMode(enabled);
+ onReportFullscreenMode(enabled);
return;
}
case DO_PERFORM_PRIVATE_COMMAND: {