summaryrefslogtreecommitdiff
path: root/core/java/android/inputmethodservice/InputMethodService.java
diff options
context:
space:
mode:
authorYohei Yukawa <yukawa@google.com>2018-08-29 19:56:02 -0700
committerYohei Yukawa <yukawa@google.com>2018-08-29 19:56:02 -0700
commit13a9ffba01d6861725523b09dfc12f57c731f461 (patch)
tree3953c7caa5ea402bd3d943ca7c10f19edded60f2 /core/java/android/inputmethodservice/InputMethodService.java
parentc96760f4f30279bdddcbdc83398bc069740970f1 (diff)
Let SoftInputWindow handle BadTokenException
After several attempts [1][2], this is our latest attempt to gracefully ignore BadTokenException an IME that is being destroyed is still handling pending showSoftInput() requests. The point is that SoftInputWindow is a hidden API. This means that instead of adding a bunch of try/catch blocks around mWindow.show() in InputMethodService we can always override SoftInputWindow#show() to inject our own code around mWindow.show(). With this CL, we can now fully track the internal lifecycle of SoftInputWindow in SoftInputWindow#mWindowState. It enables us to easily sort out cases like double fault cases discussed in Bug 113159114, where showSoftInput() requests were queued multiple times and still IMEs crash because what mWindow.show() throws for the 2nd failure is IllegaStateException not BadTokenException. [1] Id1e5f236f48c8ef01b7f157ba3f6e7ab2c26b135 6fcbb5629019489a88a9748f278d40d554cc5cdc [2] I2c21573cf972145ab08e66604cdb9344139a3f31 e4bbb1cc451c7ebdad9f92968732fc4f6c21a70c Fix: 113159114 Test: Manually verified IME switching scenario as follows. 1. Build and flush aosp_taimen-userdebug 2. make -j SoftKeyboard 3. adb install -r $OUT/system/app/SoftKeyboard/SoftKeyboard.apk 4. adb shell ime enable com.example.android.softkeyboard/.SoftKeyboard 5. Open the Dialer app and tap the top edit field. 6. Make sure that AOSP Keyboard is shown. 7. Tap the globe button on AOSP Keyboard. 8. Make sure that AOSP Keyboard is dismissed and SoftKeybaord is shown. 9. Tap the globe button on SoftKeybaord. 10. Make sure that SoftKeybaord. is dismissed and AOSP Keyboard is shown again. Test: atest CtsInputMethodTestCases CtsInputMethodServiceHostTestCases Change-Id: I1f51ed29df6b22b003ca285698e06b8f3ee5106a
Diffstat (limited to 'core/java/android/inputmethodservice/InputMethodService.java')
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java57
1 files changed, 11 insertions, 46 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index acaaf07984f0..d165889e8325 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -62,7 +62,6 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowManager;
-import android.view.WindowManager.BadTokenException;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CursorAnchorInfo;
@@ -354,7 +353,6 @@ public class InputMethodService extends AbstractInputMethodService {
SoftInputWindow mWindow;
boolean mInitialized;
boolean mWindowCreated;
- boolean mWindowAdded;
boolean mWindowVisible;
boolean mWindowWasVisible;
boolean mInShowWindow;
@@ -572,16 +570,7 @@ public class InputMethodService extends AbstractInputMethodService {
if (DEBUG) Log.v(TAG, "showSoftInput()");
boolean wasVis = isInputViewShown();
if (dispatchOnShowInputRequested(flags, false)) {
- try {
- showWindow(true);
- } catch (BadTokenException e) {
- // We have ignored BadTokenException here since Jelly Bean MR-2 (API Level 18).
- // We could ignore BadTokenException in InputMethodService#showWindow() instead,
- // but it may break assumptions for those who override #showWindow() that we can
- // detect errors in #showWindow() by checking BadTokenException.
- // TODO: Investigate its feasibility. Update JavaDoc of #showWindow() of
- // whether it's OK to override #showWindow() or not.
- }
+ showWindow(true);
}
clearInsetOfPreviousIme();
// If user uses hard keyboard, IME button should always be shown.
@@ -999,13 +988,7 @@ public class InputMethodService extends AbstractInputMethodService {
mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
mInsetsComputer);
doFinishInput();
- if (mWindowAdded) {
- // Disable exit animation for the current IME window
- // to avoid the race condition between the exit and enter animations
- // when the current IME is being switched to another one.
- mWindow.getWindow().setWindowAnimations(0);
- mWindow.dismiss();
- }
+ mWindow.dismissForDestroyIfNecessary();
if (mSettingsObserver != null) {
mSettingsObserver.unregister();
mSettingsObserver = null;
@@ -1792,7 +1775,6 @@ public class InputMethodService extends AbstractInputMethodService {
public void showWindow(boolean showInput) {
if (DEBUG) Log.v(TAG, "Showing window: showInput=" + showInput
+ " mShowInputRequested=" + mShowInputRequested
- + " mWindowAdded=" + mWindowAdded
+ " mWindowCreated=" + mWindowCreated
+ " mWindowVisible=" + mWindowVisible
+ " mInputStarted=" + mInputStarted
@@ -1802,27 +1784,12 @@ public class InputMethodService extends AbstractInputMethodService {
Log.w(TAG, "Re-entrance in to showWindow");
return;
}
-
- try {
- mWindowWasVisible = mWindowVisible;
- mInShowWindow = true;
- showWindowInner(showInput);
- } catch (BadTokenException e) {
- // BadTokenException is a normal consequence in certain situations, e.g., swapping IMEs
- // while there is a DO_SHOW_SOFT_INPUT message in the IIMethodWrapper queue.
- if (DEBUG) Log.v(TAG, "BadTokenException: IME is done.");
- mWindowVisible = false;
- mWindowAdded = false;
- // Rethrow the exception to preserve the existing behavior. Some IMEs may have directly
- // called this method and relied on this exception for some clean-up tasks.
- // TODO: Give developers a clear guideline of whether it's OK to call this method or
- // InputMethodService#requestShowSelf(int) should always be used instead.
- throw e;
- } finally {
- // TODO: Is it OK to set true when we get BadTokenException?
- mWindowWasVisible = true;
- mInShowWindow = false;
- }
+
+ mWindowWasVisible = mWindowVisible;
+ mInShowWindow = true;
+ showWindowInner(showInput);
+ mWindowWasVisible = true;
+ mInShowWindow = false;
}
void showWindowInner(boolean showInput) {
@@ -1839,9 +1806,8 @@ public class InputMethodService extends AbstractInputMethodService {
initialize();
updateFullscreenMode();
updateInputViewShown();
-
- if (!mWindowAdded || !mWindowCreated) {
- mWindowAdded = true;
+
+ if (!mWindowCreated) {
mWindowCreated = true;
initialize();
if (DEBUG) Log.v(TAG, "CALL: onCreateCandidatesView");
@@ -2867,8 +2833,7 @@ public class InputMethodService extends AbstractInputMethodService {
@Override protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
final Printer p = new PrintWriterPrinter(fout);
p.println("Input method service state for " + this + ":");
- p.println(" mWindowCreated=" + mWindowCreated
- + " mWindowAdded=" + mWindowAdded);
+ p.println(" mWindowCreated=" + mWindowCreated);
p.println(" mWindowVisible=" + mWindowVisible
+ " mWindowWasVisible=" + mWindowWasVisible
+ " mInShowWindow=" + mInShowWindow);