Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 911b505f authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Android Git Automerger
Browse files

am dc5fa185: am 133dc2d7: Merge "Fix issue #6048808: sometimes auto-correct is...

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

* commit 'dc5fa185':
  Fix issue #6048808: sometimes auto-correct is inactive
parents 5cb79935 dc5fa185
Loading
Loading
Loading
Loading
+88 −43
Original line number Original line Diff line number Diff line
@@ -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;
@@ -199,6 +198,30 @@ 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,
@@ -1191,6 +1221,7 @@ public final class InputMethodManager {
     */
     */
    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,27 +1230,42 @@ 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) {
            controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS;
            if (focusedView.onCheckIsTextEditor()) {
                controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR;
            }
        }
        if (first) {
            controlFlags |= CONTROL_WINDOW_FIRST;
        }
        
        
        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) {
        synchronized (mH) {
            try {
            try {
                final boolean isTextEditor = focusedView != null &&
                        focusedView.onCheckIsTextEditor();
                mService.windowGainedFocus(mClient, rootView.getWindowToken(),
                mService.windowGainedFocus(mClient, rootView.getWindowToken(),
                        focusedView != null, isTextEditor, softInputMode, first,
                        controlFlags, softInputMode, windowFlags, null, null);
                        windowFlags);
            } catch (RemoteException e) {
            } catch (RemoteException e) {
            }
            }
        }
        }

        if (startInput) {
            startInputInner();
        }
    }
    }
    
    
    /** @hide */
    /** @hide */
@@ -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:");
+6 −5
Original line number Original line Diff line number Diff line
@@ -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);
+78 −33
Original line number Original line Diff line number Diff line
@@ -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));

                ClientState cs = mClients.get(client.asBinder());
                if (cs == null) {
                    throw new IllegalArgumentException("unknown client "
                            + client.asBinder());
                }


                if (mCurClient == null || client == null
                        || mCurClient.client.asBinder() != client.asBinder()) {
                try {
                try {
                        // We need to check if this is the current client with
                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
                        // focus in the window manager, to allow this call to
                        // Check with the window manager to make sure this client actually
                        // be made before input is started in it.
                        // has a window with focus.  If not, reject.  This is thread safe
                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
                        // because if the focus changes some time before or after, the
                            Slog.w(TAG, "Client not active, ignoring focus gain of: " + client);
                        // next client receiving focus that has any interest in input will
                            return;
                        // 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) {
                } 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