Part of fixing issue #6006757: Keyboard dismissal lags

This adjust various paths through InputMethodManager so that the flow
in switching focus from one application to another is cleaner, resulting
in less work being done, resulting in it being able to happen quicker.

Some of the changes here avoid doing stuff when not needed, such as when
we are told to unbind but are not currently the active input.  A big part
is also a change to the flow when a window receives input.  Previously
this would first do a checkFocus() which would tell the input method to
switch focus to whatever view has focus in the window, followed by the
windowGainedFocus() call telling it the window had gained focus.  This
would result in extra work because the input method service would first
handle the focus switch, seeing the IME is currently displayed, so the IME
would remain up and reset its focus to the new view.  The app would
immediately then tell it about the window, causing the service to find out
the IME should be hidden and telling the IME, but the IME couldn't hide
itself until it had first take care of switching its input.

There is the definite potential of this breaking IME showing/hiding in
cases depending on the order things may be relying on them to happen.  I
haven't seen any problems with a brief trip through the UI.

Change-Id: I8494cbd6e19e2ab6db03f2463d9906680dda058b
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index b41e6f5..4e85425 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -355,8 +355,10 @@
                             if (mServedView != null && mServedView.isFocused()) {
                                 mServedConnecting = true;
                             }
+                            if (mActive) {
+                                startInputInner();
+                            }
                         }
-                        startInputInner();
                     }
                     return;
                 }
@@ -1127,20 +1129,26 @@
      * @hide
      */
     public void checkFocus() {
+        if (checkFocusNoStartInput()) {
+            startInputInner();
+        }
+    }
+
+    private boolean checkFocusNoStartInput() {
         // This is called a lot, so short-circuit before locking.
         if (mServedView == mNextServedView && !mNextServedNeedsStart) {
-            return;
+            return false;
         }
 
         InputConnection ic = null;
         synchronized (mH) {
             if (mServedView == mNextServedView && !mNextServedNeedsStart) {
-                return;
+                return false;
             }
             if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
                     + " next=" + mNextServedView
                     + " restart=" + mNextServedNeedsStart);
-            
+
             mNextServedNeedsStart = false;
             if (mNextServedView == null) {
                 finishInputLocked();
@@ -1148,22 +1156,22 @@
                 // but no longer do.  We should make sure the input method is
                 // no longer shown, since it serves no purpose.
                 closeCurrentInput();
-                return;
+                return false;
             }
-            
+
             ic = mServedInputConnection;
-            
+
             mServedView = mNextServedView;
             mCurrentTextBoxAttribute = null;
             mCompletions = null;
             mServedConnecting = true;
         }
-        
+
         if (ic != null) {
             ic.finishComposingText();
         }
-        
-        startInputInner();
+
+        return true;
     }
     
     void closeCurrentInput() {
@@ -1192,7 +1200,7 @@
             focusInLocked(focusedView != null ? focusedView : rootView);
         }
         
-        checkFocus();
+        boolean startInput = checkFocusNoStartInput();
         
         synchronized (mH) {
             try {
@@ -1201,6 +1209,9 @@
                 mService.windowGainedFocus(mClient, rootView.getWindowToken(),
                         focusedView != null, isTextEditor, softInputMode, first,
                         windowFlags);
+                if (startInput) {
+                    startInputInner();
+                }
             } catch (RemoteException e) {
             }
         }