Skip to content

Commit ac92087

Browse files
author
Dianne Hackborn
committed
Fix issue #6499411: Characters not displayed (but suggestion bar is working)
The problem was that when dismissing the lock screen, the window manager would briefly turn off force hiding when it started animating the transition and then turn it back on until the transition was done. This would cause it to briefly switch focus to the app behind and then take focus off it. The app would find out it got focus, and re-start input on itself, asking the input method service to do so. At this point the input method service would ask the window manager if the caller really had focus, and it may or may not be told no depending on the timing. If it is told no, then it doesn't allow the focus switch to happen at that point, ignoring the new input connection, and ultimately when focus does really switch the IME is left talking with an old dead input connection. I added some code to the input connection to make sure when we are no longer using one that we mark it inactive and can't use it. This bug was especially difficult to track down because it would only visibly break when a GC happened during this time, causing the weak reference on the input connection to become null. With this change it will now always break (though in the scenario here only if you hit the race condition correctly). Change-Id: I81a6164dc140c548da1a9736e42cd253e8238a80
1 parent 37f29ab commit ac92087

File tree

4 files changed

+48
-14
lines changed

4 files changed

+48
-14
lines changed

core/java/android/view/inputmethod/InputMethodManager.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ public final class InputMethodManager {
283283
* The InputConnection that was last retrieved from the served view.
284284
*/
285285
InputConnection mServedInputConnection;
286+
ControlledInputConnectionWrapper mServedInputConnectionWrapper;
286287
/**
287288
* The completions that were last provided by the served view.
288289
*/
@@ -418,16 +419,22 @@ public void handleMessage(Message msg) {
418419

419420
private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
420421
private final InputMethodManager mParentInputMethodManager;
422+
private boolean mActive;
421423

422424
public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
423425
final InputMethodManager inputMethodManager) {
424426
super(mainLooper, conn);
425427
mParentInputMethodManager = inputMethodManager;
428+
mActive = true;
426429
}
427430

428431
@Override
429432
public boolean isActive() {
430-
return mParentInputMethodManager.mActive;
433+
return mParentInputMethodManager.mActive && mActive;
434+
}
435+
436+
void deactivate() {
437+
mActive = false;
431438
}
432439
}
433440

@@ -666,6 +673,10 @@ void clearBindingLocked() {
666673
void clearConnectionLocked() {
667674
mCurrentTextBoxAttribute = null;
668675
mServedInputConnection = null;
676+
if (mServedInputConnectionWrapper != null) {
677+
mServedInputConnectionWrapper.deactivate();
678+
mServedInputConnectionWrapper = null;
679+
}
669680
}
670681

671682
/**
@@ -1060,7 +1071,7 @@ public void run() {
10601071
// Notify the served view that its previous input connection is finished
10611072
notifyInputConnectionFinished();
10621073
mServedInputConnection = ic;
1063-
IInputContext servedContext;
1074+
ControlledInputConnectionWrapper servedContext;
10641075
if (ic != null) {
10651076
mCursorSelStart = tba.initialSelStart;
10661077
mCursorSelEnd = tba.initialSelEnd;
@@ -1071,6 +1082,10 @@ public void run() {
10711082
} else {
10721083
servedContext = null;
10731084
}
1085+
if (mServedInputConnectionWrapper != null) {
1086+
mServedInputConnectionWrapper.deactivate();
1087+
}
1088+
mServedInputConnectionWrapper = servedContext;
10741089

10751090
try {
10761091
if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
@@ -1286,6 +1301,7 @@ public void onWindowFocus(View rootView, View focusedView, int softInputMode,
12861301
// we'll just do a window focus gain and call it a day.
12871302
synchronized (mH) {
12881303
try {
1304+
if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
12891305
mService.windowGainedFocus(mClient, rootView.getWindowToken(),
12901306
controlFlags, softInputMode, windowFlags, null, null);
12911307
} catch (RemoteException e) {

services/java/com/android/server/InputMethodManagerService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1667,7 +1667,8 @@ public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder wind
16671667
}
16681668

16691669
if (mCurFocusedWindow == windowToken) {
1670-
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client);
1670+
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
1671+
+ " attribute=" + attribute);
16711672
if (attribute != null) {
16721673
return startInputUncheckedLocked(cs, inputContext, attribute,
16731674
controlFlags);

services/java/com/android/server/wm/WindowAnimator.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,19 @@ private void updateWindowsAndWallpaperLocked() {
269269
mPendingLayoutChanges);
270270
}
271271
mService.mFocusMayChange = true;
272-
} else if (win.isReadyForDisplay()) {
272+
}
273+
if (win.isReadyForDisplay()) {
273274
mForceHiding = true;
274275
}
276+
if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG,
277+
"Force hide " + mForceHiding
278+
+ " hasSurface=" + win.mHasSurface
279+
+ " policyVis=" + win.mPolicyVisibility
280+
+ " destroying=" + win.mDestroying
281+
+ " attHidden=" + win.mAttachedHidden
282+
+ " vis=" + win.mViewVisibility
283+
+ " hidden=" + win.mRootToken.hidden
284+
+ " anim=" + win.mWinAnimator.mAnimation);
275285
} else if (mPolicy.canBeForceHidden(win, win.mAttrs)) {
276286
final boolean changed;
277287
if (mForceHiding) {

services/java/com/android/server/wm/WindowManagerService.java

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,7 +1177,9 @@ static boolean canBeImeTarget(WindowState w) {
11771177
if (!w.isVisibleOrAdding()) {
11781178
Slog.i(TAG, " mSurface=" + w.mWinAnimator.mSurface
11791179
+ " relayoutCalled=" + w.mRelayoutCalled + " viewVis=" + w.mViewVisibility
1180-
+ " policyVis=" + w.mPolicyVisibility + " attachHid=" + w.mAttachedHidden
1180+
+ " policyVis=" + w.mPolicyVisibility
1181+
+ " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1182+
+ " attachHid=" + w.mAttachedHidden
11811183
+ " exiting=" + w.mExiting + " destroying=" + w.mDestroying);
11821184
if (w.mAppToken != null) {
11831185
Slog.i(TAG, " mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
@@ -7234,9 +7236,11 @@ public boolean inputMethodClientHasFocus(IInputMethodClient client) {
72347236
WindowState imFocus;
72357237
if (idx > 0) {
72367238
imFocus = mWindows.get(idx-1);
7237-
//Log.i(TAG, "Desired input method target: " + imFocus);
7238-
//Log.i(TAG, "Current focus: " + this.mCurrentFocus);
7239-
//Log.i(TAG, "Last focus: " + this.mLastFocus);
7239+
if (DEBUG_INPUT_METHOD) {
7240+
Slog.i(TAG, "Desired input method target: " + imFocus);
7241+
Slog.i(TAG, "Current focus: " + this.mCurrentFocus);
7242+
Slog.i(TAG, "Last focus: " + this.mLastFocus);
7243+
}
72407244
if (imFocus != null) {
72417245
// This may be a starting window, in which case we still want
72427246
// to count it as okay.
@@ -7247,17 +7251,20 @@ public boolean inputMethodClientHasFocus(IInputMethodClient client) {
72477251
for (int i=0; i<imFocus.mAppToken.windows.size(); i++) {
72487252
WindowState w = imFocus.mAppToken.windows.get(i);
72497253
if (w != imFocus) {
7250-
//Log.i(TAG, "Switching to real app window: " + w);
7254+
Log.i(TAG, "Switching to real app window: " + w);
72517255
imFocus = w;
72527256
break;
72537257
}
72547258
}
72557259
}
7256-
//Log.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7257-
//if (imFocus.mSession.mClient != null) {
7258-
// Log.i(TAG, "IM target client binder: " + imFocus.mSession.mClient.asBinder());
7259-
// Log.i(TAG, "Requesting client binder: " + client.asBinder());
7260-
//}
7260+
if (DEBUG_INPUT_METHOD) {
7261+
Slog.i(TAG, "IM target client: " + imFocus.mSession.mClient);
7262+
if (imFocus.mSession.mClient != null) {
7263+
Slog.i(TAG, "IM target client binder: "
7264+
+ imFocus.mSession.mClient.asBinder());
7265+
Slog.i(TAG, "Requesting client binder: " + client.asBinder());
7266+
}
7267+
}
72617268
if (imFocus.mSession.mClient != null &&
72627269
imFocus.mSession.mClient.asBinder() == client.asBinder()) {
72637270
return true;

0 commit comments

Comments
 (0)