Track by which client the last focused window was reported.

To diagnose race conditions like issue #25373872, we want to track
which input method client corresponds to IMMS#mCurFocusedWindow.

Note that IMMS#mCurClient does not always correspond to
IMMS#mCurFocusedWindow, because input method clients can report the
window focus gain only, without requesting to be bound to IME.

Bug: 25373872
Change-Id: Iad121669c0f3db4461245dc80ff3fdee469abb79
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 40f7c5c..5e4f2b2 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -309,11 +309,18 @@
     ClientState mCurClient;
 
     /**
-     * The last window token that gained focus.
+     * The last window token that we confirmed to be focused.  This is always updated upon reports
+     * from the input method client.  If the window state is already changed before the report is
+     * handled, this field just keeps the last value.
      */
     IBinder mCurFocusedWindow;
 
     /**
+     * The client by which {@link #mCurFocusedWindow} was reported.  Used only for debugging.
+     */
+    ClientState mCurFocusedWindowClient;
+
+    /**
      * The input context last provided by the current client.
      */
     IInputContext mCurInputContext;
@@ -1199,6 +1206,9 @@
                 if (mCurClient == cs) {
                     mCurClient = null;
                 }
+                if (mCurFocusedWindowClient == cs) {
+                    mCurFocusedWindowClient = null;
+                }
             }
         }
     }
@@ -2194,6 +2204,7 @@
                     return null;
                 }
                 mCurFocusedWindow = windowToken;
+                mCurFocusedWindowClient = cs;
 
                 // Should we auto-show the IME even if the caller has not
                 // specified what should be done with it?
@@ -3705,6 +3716,7 @@
 
         IInputMethod method;
         ClientState client;
+        ClientState focusedWindowClient;
 
         final Printer p = new PrintWriterPrinter(pw);
 
@@ -3729,6 +3741,8 @@
             client = mCurClient;
             p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
             p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
+            focusedWindowClient = mCurFocusedWindowClient;
+            p.println("  mCurFocusedWindowClient=" + focusedWindowClient);
             p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
                     + " mBoundToMethod=" + mBoundToMethod);
             p.println("  mCurToken=" + mCurToken);
@@ -3760,6 +3774,20 @@
             p.println("No input method client.");
         }
 
+        if (focusedWindowClient != null && client != focusedWindowClient) {
+            p.println(" ");
+            p.println("Warning: Current input method client doesn't match the last focused. "
+                    + "window.");
+            p.println("Dumping input method client in the last focused window just in case.");
+            p.println(" ");
+            pw.flush();
+            try {
+                focusedWindowClient.client.asBinder().dump(fd, args);
+            } catch (RemoteException e) {
+                p.println("Input method client in focused window dead: " + e);
+            }
+        }
+
         p.println(" ");
         if (method != null) {
             pw.flush();