am 133dc2d7: Merge "Fix issue #6048808: sometimes auto-correct is inactive" into ics-mr1

* commit '133dc2d7aecc68990c363c861716b134910a4ced':
  Fix issue #6048808: sometimes auto-correct is inactive
This commit is contained in:
Dianne Hackborn
2012-02-24 15:38:07 -08:00
committed by Android Git Automerger
3 changed files with 177 additions and 86 deletions

View File

@ -26,7 +26,6 @@ import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult; import com.android.internal.view.InputBindResult;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@ -198,7 +197,31 @@ public final class InputMethodManager {
static final Object mInstanceSync = new Object(); static final Object mInstanceSync = new Object();
static InputMethodManager mInstance; static InputMethodManager mInstance;
/**
* @hide Flag for IInputMethodManager.windowGainedFocus: a view in
* the window has input focus.
*/
public static final int CONTROL_WINDOW_VIEW_HAS_FOCUS = 1<<0;
/**
* @hide Flag for IInputMethodManager.windowGainedFocus: the focus
* is a text editor.
*/
public static final int CONTROL_WINDOW_IS_TEXT_EDITOR = 1<<1;
/**
* @hide Flag for IInputMethodManager.windowGainedFocus: this is the first
* time the window has gotten focus.
*/
public static final int CONTROL_WINDOW_FIRST = 1<<2;
/**
* @hide Flag for IInputMethodManager.startInput: this is the first
* time the window has gotten focus.
*/
public static final int CONTROL_START_INITIAL = 1<<8;
final IInputMethodManager mService; final IInputMethodManager mService;
final Looper mMainLooper; final Looper mMainLooper;
@ -216,7 +239,7 @@ public final class InputMethodManager {
/** /**
* Set whenever this client becomes inactive, to know we need to reset * Set whenever this client becomes inactive, to know we need to reset
* state with the IME then next time we receive focus. * state with the IME the next time we receive focus.
*/ */
boolean mHasBeenInactive = true; boolean mHasBeenInactive = true;
@ -242,11 +265,6 @@ public final class InputMethodManager {
* we get around to updating things. * we get around to updating things.
*/ */
View mNextServedView; View mNextServedView;
/**
* True if we should restart input in the next served view, even if the
* view hasn't actually changed from the current serve view.
*/
boolean mNextServedNeedsStart;
/** /**
* This is set when we are in the process of connecting, to determine * This is set when we are in the process of connecting, to determine
* when we have actually finished. * when we have actually finished.
@ -331,7 +349,7 @@ public final class InputMethodManager {
mCurId = res.id; mCurId = res.id;
mBindSequence = res.sequence; mBindSequence = res.sequence;
} }
startInputInner(); startInputInner(null, 0, 0, 0);
return; return;
} }
case MSG_UNBIND: { case MSG_UNBIND: {
@ -362,7 +380,7 @@ public final class InputMethodManager {
} }
} }
if (startInput) { if (startInput) {
startInputInner(); startInputInner(null, 0, 0, 0);
} }
return; return;
} }
@ -952,10 +970,11 @@ public final class InputMethodManager {
mServedConnecting = true; mServedConnecting = true;
} }
startInputInner(); startInputInner(null, 0, 0, 0);
} }
void startInputInner() { boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
int windowFlags) {
final View view; final View view;
synchronized (mH) { synchronized (mH) {
view = mServedView; view = mServedView;
@ -964,7 +983,7 @@ public final class InputMethodManager {
if (DEBUG) Log.v(TAG, "Starting input: view=" + view); if (DEBUG) Log.v(TAG, "Starting input: view=" + view);
if (view == null) { if (view == null) {
if (DEBUG) Log.v(TAG, "ABORT input: no served view!"); if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
return; return false;
} }
} }
@ -977,7 +996,7 @@ public final class InputMethodManager {
// If the view doesn't have a handler, something has changed out // If the view doesn't have a handler, something has changed out
// from under us, so just bail. // from under us, so just bail.
if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!"); if (DEBUG) Log.v(TAG, "ABORT input: no handler for view!");
return; return false;
} }
if (vh.getLooper() != Looper.myLooper()) { if (vh.getLooper() != Looper.myLooper()) {
// The view is running on a different thread than our own, so // The view is running on a different thread than our own, so
@ -985,10 +1004,10 @@ public final class InputMethodManager {
if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread"); if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
vh.post(new Runnable() { vh.post(new Runnable() {
public void run() { public void run() {
startInputInner(); startInputInner(null, 0, 0, 0);
} }
}); });
return; return false;
} }
// Okay we are now ready to call into the served view and have it // Okay we are now ready to call into the served view and have it
@ -1008,12 +1027,14 @@ public final class InputMethodManager {
if (DEBUG) Log.v(TAG, if (DEBUG) Log.v(TAG,
"Starting input: finished by someone else (view=" "Starting input: finished by someone else (view="
+ mServedView + " conn=" + mServedConnecting + ")"); + mServedView + " conn=" + mServedConnecting + ")");
return; return false;
} }
// If we already have a text box, then this view is already // If we already have a text box, then this view is already
// connected so we want to restart it. // connected so we want to restart it.
final boolean initial = mCurrentTextBoxAttribute == null; if (mCurrentTextBoxAttribute == null) {
controlFlags |= CONTROL_START_INITIAL;
}
// Hook 'em up and let 'er rip. // Hook 'em up and let 'er rip.
mCurrentTextBoxAttribute = tba; mCurrentTextBoxAttribute = tba;
@ -1033,9 +1054,17 @@ public final class InputMethodManager {
try { try {
if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic=" if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
+ ic + " tba=" + tba + " initial=" + initial); + ic + " tba=" + tba + " controlFlags=#"
InputBindResult res = mService.startInput(mClient, + Integer.toHexString(controlFlags));
servedContext, tba, initial, true); InputBindResult res;
if (windowGainingFocus != null) {
res = mService.windowGainedFocus(mClient, windowGainingFocus,
controlFlags, softInputMode, windowFlags,
tba, servedContext);
} else {
res = mService.startInput(mClient,
servedContext, tba, controlFlags);
}
if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res); if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
if (res != null) { if (res != null) {
if (res.id != null) { if (res.id != null) {
@ -1044,7 +1073,7 @@ public final class InputMethodManager {
} else if (mCurMethod == null) { } else if (mCurMethod == null) {
// This means there is no input method available. // This means there is no input method available.
if (DEBUG) Log.v(TAG, "ABORT input: no input method!"); if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
return; return true;
} }
} }
if (mCurMethod != null && mCompletions != null) { if (mCurMethod != null && mCompletions != null) {
@ -1057,6 +1086,8 @@ public final class InputMethodManager {
Log.w(TAG, "IME died: " + mCurId, e); Log.w(TAG, "IME died: " + mCurId, e);
} }
} }
return true;
} }
/** /**
@ -1133,27 +1164,26 @@ public final class InputMethodManager {
* @hide * @hide
*/ */
public void checkFocus() { public void checkFocus() {
if (checkFocusNoStartInput()) { if (checkFocusNoStartInput(false)) {
startInputInner(); startInputInner(null, 0, 0, 0);
} }
} }
private boolean checkFocusNoStartInput() { private boolean checkFocusNoStartInput(boolean forceNewFocus) {
// This is called a lot, so short-circuit before locking. // This is called a lot, so short-circuit before locking.
if (mServedView == mNextServedView && !mNextServedNeedsStart) { if (mServedView == mNextServedView && !forceNewFocus) {
return false; return false;
} }
InputConnection ic = null; InputConnection ic = null;
synchronized (mH) { synchronized (mH) {
if (mServedView == mNextServedView && !mNextServedNeedsStart) { if (mServedView == mNextServedView && !forceNewFocus) {
return false; return false;
} }
if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
+ " next=" + mNextServedView + " next=" + mNextServedView
+ " restart=" + mNextServedNeedsStart); + " forceNewFocus=" + forceNewFocus);
mNextServedNeedsStart = false;
if (mNextServedView == null) { if (mNextServedView == null) {
finishInputLocked(); finishInputLocked();
// In this case, we used to have a focused view on the window, // In this case, we used to have a focused view on the window,
@ -1184,13 +1214,14 @@ public final class InputMethodManager {
} catch (RemoteException e) { } catch (RemoteException e) {
} }
} }
/** /**
* Called by ViewAncestor when its window gets input focus. * Called by ViewAncestor when its window gets input focus.
* @hide * @hide
*/ */
public void onWindowFocus(View rootView, View focusedView, int softInputMode, public void onWindowFocus(View rootView, View focusedView, int softInputMode,
boolean first, int windowFlags) { boolean first, int windowFlags) {
boolean forceNewFocus = false;
synchronized (mH) { synchronized (mH) {
if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
+ " softInputMode=" + softInputMode + " softInputMode=" + softInputMode
@ -1199,26 +1230,41 @@ public final class InputMethodManager {
if (mHasBeenInactive) { if (mHasBeenInactive) {
if (DEBUG) Log.v(TAG, "Has been inactive! Starting fresh"); if (DEBUG) Log.v(TAG, "Has been inactive! Starting fresh");
mHasBeenInactive = false; mHasBeenInactive = false;
mNextServedNeedsStart = true; forceNewFocus = true;
} }
focusInLocked(focusedView != null ? focusedView : rootView); focusInLocked(focusedView != null ? focusedView : rootView);
} }
boolean startInput = checkFocusNoStartInput(); int controlFlags = 0;
if (focusedView != null) {
synchronized (mH) { controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS;
try { if (focusedView.onCheckIsTextEditor()) {
final boolean isTextEditor = focusedView != null && controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR;
focusedView.onCheckIsTextEditor();
mService.windowGainedFocus(mClient, rootView.getWindowToken(),
focusedView != null, isTextEditor, softInputMode, first,
windowFlags);
} catch (RemoteException e) {
} }
} }
if (first) {
if (startInput) { controlFlags |= CONTROL_WINDOW_FIRST;
startInputInner(); }
if (checkFocusNoStartInput(forceNewFocus)) {
// We need to restart input on the current focus view. This
// should be done in conjunction with telling the system service
// about the window gaining focus, to help make the transition
// smooth.
if (startInputInner(rootView.getWindowToken(),
controlFlags, softInputMode, windowFlags)) {
return;
}
}
// For some reason we didn't do a startInput + windowFocusGain, so
// we'll just do a window focus gain and call it a day.
synchronized (mH) {
try {
mService.windowGainedFocus(mClient, rootView.getWindowToken(),
controlFlags, softInputMode, windowFlags, null, null);
} catch (RemoteException e) {
}
} }
} }
@ -1649,8 +1695,7 @@ public final class InputMethodManager {
p.println(" mCurMethod=" + mCurMethod); p.println(" mCurMethod=" + mCurMethod);
p.println(" mCurRootView=" + mCurRootView); p.println(" mCurRootView=" + mCurRootView);
p.println(" mServedView=" + mServedView); p.println(" mServedView=" + mServedView);
p.println(" mNextServedNeedsStart=" + mNextServedNeedsStart p.println(" mNextServedView=" + mNextServedView);
+ " mNextServedView=" + mNextServedView);
p.println(" mServedConnecting=" + mServedConnecting); p.println(" mServedConnecting=" + mServedConnecting);
if (mCurrentTextBoxAttribute != null) { if (mCurrentTextBoxAttribute != null) {
p.println(" mCurrentTextBoxAttribute:"); p.println(" mCurrentTextBoxAttribute:");

View File

@ -43,16 +43,17 @@ interface IInputMethodManager {
void removeClient(in IInputMethodClient client); void removeClient(in IInputMethodClient client);
InputBindResult startInput(in IInputMethodClient client, InputBindResult startInput(in IInputMethodClient client,
IInputContext inputContext, in EditorInfo attribute, IInputContext inputContext, in EditorInfo attribute, int controlFlags);
boolean initial, boolean needResult);
void finishInput(in IInputMethodClient client); void finishInput(in IInputMethodClient client);
boolean showSoftInput(in IInputMethodClient client, int flags, boolean showSoftInput(in IInputMethodClient client, int flags,
in ResultReceiver resultReceiver); in ResultReceiver resultReceiver);
boolean hideSoftInput(in IInputMethodClient client, int flags, boolean hideSoftInput(in IInputMethodClient client, int flags,
in ResultReceiver resultReceiver); in ResultReceiver resultReceiver);
void windowGainedFocus(in IInputMethodClient client, in IBinder windowToken, // Report that a window has gained focus. If 'attribute' is non-null,
boolean viewHasFocus, boolean isTextEditor, // this will also do a startInput.
int softInputMode, boolean first, int windowFlags); InputBindResult windowGainedFocus(in IInputMethodClient client, in IBinder windowToken,
int controlFlags, int softInputMode, int windowFlags,
in EditorInfo attribute, IInputContext inputContext);
void showInputMethodPickerFromClient(in IInputMethodClient client); void showInputMethodPickerFromClient(in IInputMethodClient client);
void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId); void showInputMethodAndSubtypeEnablerFromClient(in IInputMethodClient client, String topId);

View File

@ -780,7 +780,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return flags; return flags;
} }
InputBindResult attachNewInputLocked(boolean initial, boolean needResult) { InputBindResult attachNewInputLocked(boolean initial) {
if (!mBoundToMethod) { if (!mBoundToMethod) {
executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO( executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
MSG_BIND_INPUT, mCurMethod, mCurClient.binding)); MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
@ -798,14 +798,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input"); if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
showCurrentInputLocked(getAppShowFlags(), null); showCurrentInputLocked(getAppShowFlags(), null);
} }
return needResult return new InputBindResult(session.session, mCurId, mCurSeq);
? new InputBindResult(session.session, mCurId, mCurSeq)
: null;
} }
InputBindResult startInputLocked(IInputMethodClient client, InputBindResult startInputLocked(IInputMethodClient client,
IInputContext inputContext, EditorInfo attribute, IInputContext inputContext, EditorInfo attribute, int controlFlags) {
boolean initial, boolean needResult) {
// If no method is currently selected, do nothing. // If no method is currently selected, do nothing.
if (mCurMethodId == null) { if (mCurMethodId == null) {
return mNoBinding; return mNoBinding;
@ -831,6 +828,16 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
} catch (RemoteException e) { } catch (RemoteException e) {
} }
return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
}
InputBindResult startInputUncheckedLocked(ClientState cs,
IInputContext inputContext, EditorInfo attribute, int controlFlags) {
// If no method is currently selected, do nothing.
if (mCurMethodId == null) {
return mNoBinding;
}
if (mCurClient != cs) { if (mCurClient != cs) {
// If the client is changing, we need to switch over to the new // If the client is changing, we need to switch over to the new
// one. // one.
@ -861,7 +868,8 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if (cs.curSession != null) { if (cs.curSession != null) {
// Fast case: if we are already connected to the input method, // Fast case: if we are already connected to the input method,
// then just return it. // then just return it.
return attachNewInputLocked(initial, needResult); return attachNewInputLocked(
(controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
} }
if (mHaveConnection) { if (mHaveConnection) {
if (mCurMethod != null) { if (mCurMethod != null) {
@ -942,13 +950,11 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override @Override
public InputBindResult startInput(IInputMethodClient client, public InputBindResult startInput(IInputMethodClient client,
IInputContext inputContext, EditorInfo attribute, IInputContext inputContext, EditorInfo attribute, int controlFlags) {
boolean initial, boolean needResult) {
synchronized (mMethodMap) { synchronized (mMethodMap) {
final long ident = Binder.clearCallingIdentity(); final long ident = Binder.clearCallingIdentity();
try { try {
return startInputLocked(client, inputContext, attribute, return startInputLocked(client, inputContext, attribute, controlFlags);
initial, needResult);
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
} }
@ -991,7 +997,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
mCurClient.curSession = new SessionState(mCurClient, mCurClient.curSession = new SessionState(mCurClient,
method, session); method, session);
mCurClient.sessionRequested = false; mCurClient.sessionRequested = false;
InputBindResult res = attachNewInputLocked(true, true); InputBindResult res = attachNewInputLocked(true);
if (res.method != null) { if (res.method != null) {
executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO( executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
MSG_BIND_METHOD, mCurClient.client, res)); MSG_BIND_METHOD, mCurClient.client, res));
@ -1476,36 +1482,45 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
} }
@Override @Override
public void windowGainedFocus(IInputMethodClient client, IBinder windowToken, public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
boolean viewHasFocus, boolean isTextEditor, int softInputMode, int controlFlags, int softInputMode, int windowFlags,
boolean first, int windowFlags) { EditorInfo attribute, IInputContext inputContext) {
InputBindResult res = null;
long ident = Binder.clearCallingIdentity(); long ident = Binder.clearCallingIdentity();
try { try {
synchronized (mMethodMap) { synchronized (mMethodMap) {
if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder() if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
+ " viewHasFocus=" + viewHasFocus + " controlFlags=#" + Integer.toHexString(controlFlags)
+ " isTextEditor=" + isTextEditor
+ " softInputMode=#" + Integer.toHexString(softInputMode) + " softInputMode=#" + Integer.toHexString(softInputMode)
+ " first=" + first + " flags=#" + " windowFlags=#" + Integer.toHexString(windowFlags));
+ Integer.toHexString(windowFlags));
if (mCurClient == null || client == null ClientState cs = mClients.get(client.asBinder());
|| mCurClient.client.asBinder() != client.asBinder()) { if (cs == null) {
try { throw new IllegalArgumentException("unknown client "
// We need to check if this is the current client with + client.asBinder());
// focus in the window manager, to allow this call to }
// be made before input is started in it.
if (!mIWindowManager.inputMethodClientHasFocus(client)) { try {
Slog.w(TAG, "Client not active, ignoring focus gain of: " + client); if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
return; // Check with the window manager to make sure this client actually
} // has a window with focus. If not, reject. This is thread safe
} catch (RemoteException e) { // because if the focus changes some time before or after, the
// next client receiving focus that has any interest in input will
// be calling through here after that change happens.
Slog.w(TAG, "Focus gain on non-focused client " + cs.client
+ " (uid=" + cs.uid + " pid=" + cs.pid + ")");
return null;
} }
} catch (RemoteException e) {
} }
if (mCurFocusedWindow == windowToken) { if (mCurFocusedWindow == windowToken) {
Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client); Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client);
return; if (attribute != null) {
return startInputUncheckedLocked(cs, inputContext, attribute,
controlFlags);
}
return null;
} }
mCurFocusedWindow = windowToken; mCurFocusedWindow = windowToken;
@ -1521,6 +1536,14 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
== WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
|| mRes.getConfiguration().isLayoutSizeAtLeast( || mRes.getConfiguration().isLayoutSizeAtLeast(
Configuration.SCREENLAYOUT_SIZE_LARGE); Configuration.SCREENLAYOUT_SIZE_LARGE);
final boolean isTextEditor =
(controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
// We want to start input before showing the IME, but after closing
// it. We want to do this after closing it to help the IME disappear
// more quickly (not get stuck behind it initializing itself for the
// new focused input, even if its window wants to hide the IME).
boolean didStart = false;
switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) { switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED: case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
@ -1536,12 +1559,17 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
// There is a focus view, and we are navigating forward // There is a focus view, and we are navigating forward
// into the window, so show the input window for the user. // into the window, so show the input window for the user.
// We only do this automatically if the window an resize // We only do this automatically if the window can resize
// to accomodate the IME (so what the user sees will give // to accommodate the IME (so what the user sees will give
// them good context without input information being obscured // them good context without input information being obscured
// by the IME) or if running on a large screen where there // by the IME) or if running on a large screen where there
// is more room for the target window + IME. // is more room for the target window + IME.
if (DEBUG) Slog.v(TAG, "Unspecified window will show input"); if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
if (attribute != null) {
res = startInputUncheckedLocked(cs, inputContext, attribute,
controlFlags);
didStart = true;
}
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null); showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
} }
break; break;
@ -1563,18 +1591,35 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
if ((softInputMode & if ((softInputMode &
WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) { WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
if (DEBUG) Slog.v(TAG, "Window asks to show input going forward"); if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
if (attribute != null) {
res = startInputUncheckedLocked(cs, inputContext, attribute,
controlFlags);
didStart = true;
}
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null); showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
} }
break; break;
case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE: case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
if (DEBUG) Slog.v(TAG, "Window asks to always show input"); if (DEBUG) Slog.v(TAG, "Window asks to always show input");
if (attribute != null) {
res = startInputUncheckedLocked(cs, inputContext, attribute,
controlFlags);
didStart = true;
}
showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null); showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
break; break;
} }
if (!didStart && attribute != null) {
res = startInputUncheckedLocked(cs, inputContext, attribute,
controlFlags);
}
} }
} finally { } finally {
Binder.restoreCallingIdentity(ident); Binder.restoreCallingIdentity(ident);
} }
return res;
} }
@Override @Override