Merge "Always send WindowToken when starting IME input"
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 7e6af49..63ee624 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -1239,7 +1239,7 @@
     }
 
     boolean startInputInner(@InputMethodClient.StartInputReason final int startInputReason,
-            IBinder windowGainingFocus, int controlFlags, int softInputMode,
+            @Nullable IBinder windowGainingFocus, int controlFlags, int softInputMode,
             int windowFlags) {
         final View view;
         synchronized (mH) {
@@ -1256,6 +1256,20 @@
             }
         }
 
+        if (windowGainingFocus == null) {
+            windowGainingFocus = view.getWindowToken();
+            if (windowGainingFocus == null) {
+                Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
+                return false;
+            }
+            controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS;
+            if (view.onCheckIsTextEditor()) {
+                controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR;
+            }
+            softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
+            windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
+        }
+
         // Now we need to get an input connection from the served view.
         // This is complicated in a couple ways: we can't be holding our lock
         // when calling out to the view, and we need to make sure we call into
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index caea282..20875a9 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1827,50 +1827,6 @@
 
     @GuardedBy("mMethodMap")
     @NonNull
-    InputBindResult startInputLocked(
-            /* @InputMethodClient.StartInputReason */ final int startInputReason,
-            IInputMethodClient client, IInputContext inputContext,
-            /* @InputConnectionInspector.missingMethods */ final int missingMethods,
-            @Nullable EditorInfo attribute, int controlFlags) {
-        // If no method is currently selected, do nothing.
-        if (mCurMethodId == null) {
-            return InputBindResult.NO_IME;
-        }
-
-        ClientState cs = mClients.get(client.asBinder());
-        if (cs == null) {
-            throw new IllegalArgumentException("unknown client "
-                    + client.asBinder());
-        }
-
-        if (attribute == null) {
-            Slog.w(TAG, "Ignoring startInput with null EditorInfo."
-                    + " uid=" + cs.uid + " pid=" + cs.pid);
-            return InputBindResult.NULL_EDITOR_INFO;
-        }
-
-        try {
-            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
-                // Check with the window manager to make sure this client actually
-                // has a window with focus.  If not, reject.  This is thread safe
-                // 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.
-                if (DEBUG) {
-                    Slog.w(TAG, "Starting input on non-focused client " + cs.client
-                            + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
-                }
-                return InputBindResult.NOT_IME_TARGET_WINDOW;
-            }
-        } catch (RemoteException e) {
-        }
-
-        return startInputUncheckedLocked(cs, inputContext, missingMethods, attribute,
-                controlFlags, startInputReason);
-    }
-
-    @GuardedBy("mMethodMap")
-    @NonNull
     InputBindResult startInputUncheckedLocked(@NonNull ClientState cs, IInputContext inputContext,
             /* @InputConnectionInspector.missingMethods */ final int missingMethods,
             @NonNull EditorInfo attribute, int controlFlags,
@@ -1997,36 +1953,6 @@
         return InputBindResult.IME_NOT_CONNECTED;
     }
 
-    @NonNull
-    private InputBindResult startInput(
-            /* @InputMethodClient.StartInputReason */ final int startInputReason,
-            IInputMethodClient client, IInputContext inputContext,
-            /* @InputConnectionInspector.missingMethods */ final int missingMethods,
-            @Nullable EditorInfo attribute, int controlFlags) {
-        if (!calledFromValidUser()) {
-            return InputBindResult.INVALID_USER;
-        }
-        synchronized (mMethodMap) {
-            if (DEBUG) {
-                Slog.v(TAG, "startInput: reason="
-                        + InputMethodClient.getStartInputReason(startInputReason)
-                        + " client = " + client.asBinder()
-                        + " inputContext=" + inputContext
-                        + " missingMethods="
-                        + InputConnectionInspector.getMissingMethodFlagsAsString(missingMethods)
-                        + " attribute=" + attribute
-                        + " controlFlags=#" + Integer.toHexString(controlFlags));
-            }
-            final long ident = Binder.clearCallingIdentity();
-            try {
-                return startInputLocked(startInputReason, client, inputContext, missingMethods,
-                        attribute, controlFlags);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-        }
-    }
-
     @Override
     public void finishInput(IInputMethodClient client) {
     }
@@ -2741,15 +2667,13 @@
             int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
             /* @InputConnectionInspector.missingMethods */ final int missingMethods,
             int unverifiedTargetSdkVersion) {
-        final InputBindResult result;
-        if (windowToken != null) {
-            result = windowGainedFocus(startInputReason, client, windowToken, controlFlags,
-                    softInputMode, windowFlags, attribute, inputContext, missingMethods,
-                    unverifiedTargetSdkVersion);
-        } else {
-            result = startInput(startInputReason, client, inputContext, missingMethods, attribute,
-                    controlFlags);
+        if (windowToken == null) {
+            Slog.e(TAG, "windowToken cannot be null.");
+            return InputBindResult.NULL;
         }
+        final InputBindResult result = startInputOrWindowGainedFocusInternal(startInputReason,
+                client, windowToken, controlFlags, softInputMode, windowFlags, attribute,
+                inputContext, missingMethods, unverifiedTargetSdkVersion);
         if (result == null) {
             // This must never happen, but just in case.
             Slog.wtf(TAG, "InputBindResult is @NonNull. startInputReason="
@@ -2762,9 +2686,9 @@
     }
 
     @NonNull
-    private InputBindResult windowGainedFocus(
+    private InputBindResult startInputOrWindowGainedFocusInternal(
             /* @InputMethodClient.StartInputReason */ final int startInputReason,
-            IInputMethodClient client, IBinder windowToken, int controlFlags,
+            IInputMethodClient client, @NonNull IBinder windowToken, int controlFlags,
             /* @android.view.WindowManager.LayoutParams.SoftInputModeFlags */ int softInputMode,
             int windowFlags, EditorInfo attribute, IInputContext inputContext,
             /* @InputConnectionInspector.missingMethods */  final int missingMethods,
@@ -2775,7 +2699,7 @@
         long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mMethodMap) {
-                if (DEBUG) Slog.v(TAG, "windowGainedFocus: reason="
+                if (DEBUG) Slog.v(TAG, "startInputOrWindowGainedFocusInternal: reason="
                         + InputMethodClient.getStartInputReason(startInputReason)
                         + " client=" + client.asBinder()
                         + " inputContext=" + inputContext