Allow MSIME to set inactive when window loses focus.

MSIME doesn't work when existing InputConnection is restored. The fix is
to allow MSIME to activate connection when window gains focus and set
inactive when window loses focus. This mimics single session IME.

Bug: 128751901
Test: Manually tested using steps in bug.
Change-Id: I22cef6c1dacb0ca402840da94a2bf02b989da447
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
index 0604f6a..4b02085 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegate.java
@@ -374,4 +374,15 @@
     public boolean isUidAllowedOnDisplay(int displayId, int uid) {
         return mImpl.isUidAllowedOnDisplay(displayId, uid);
     }
+
+    /**
+     * Can be called by MSIME to activate/deactivate a client when it is gaining/losing focus
+     * respectively.
+     *
+     * @param clientId client ID to activate/deactivate.
+     * @param active {@code true} to activate a client.
+     */
+    public void setActive(int clientId, boolean active) {
+        mImpl.setActive(clientId, active);
+    }
 }
diff --git a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
index bbe3a7f..04db8d6 100644
--- a/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
+++ b/core/java/android/inputmethodservice/MultiClientInputMethodServiceDelegateImpl.java
@@ -190,4 +190,8 @@
     boolean isUidAllowedOnDisplay(int displayId, int uid) {
         return mPrivOps.isUidAllowedOnDisplay(displayId, uid);
     }
+
+    void setActive(int clientId, boolean active) {
+        mPrivOps.setActive(clientId, active);
+    }
 }
diff --git a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
index 69d9ccc..b5f2147 100644
--- a/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
+++ b/core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl
@@ -31,4 +31,5 @@
             in IMultiClientInputMethodSession multiClientSession, in InputChannel writeChannel);
     void reportImeWindowTarget(int clientId, int targetWindowHandle, in IBinder imeWindowToken);
     boolean isUidAllowedOnDisplay(int displayId, int uid);
+    void setActive(int clientId, boolean active);
 }
diff --git a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
index 9220117..1cf6887 100644
--- a/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
+++ b/core/java/com/android/internal/inputmethod/MultiClientInputMethodPrivilegedOperations.java
@@ -212,4 +212,21 @@
         }
     }
 
+    /**
+     * Calls {@link IMultiClientInputMethodPrivilegedOperations#setActive(int, boolean)}.
+     * @param clientId client ID to be set active/inactive
+     * @param active {@code true} set set active.
+     */
+    @AnyThread
+    public void setActive(int clientId, boolean active) {
+        final IMultiClientInputMethodPrivilegedOperations ops = mOps.getAndWarnIfNull();
+        if (ops == null) {
+            return;
+        }
+        try {
+            ops.setActive(clientId, active);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index a2515c8..580150e 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1228,6 +1228,24 @@
         public boolean isUidAllowedOnDisplay(int displayId, int uid) {
             return mIWindowManagerInternal.isUidAllowedOnDisplay(displayId, uid);
         }
+
+        @BinderThread
+        @Override
+        public void setActive(int clientId, boolean active) {
+            synchronized (mPerUserData.mLock) {
+                final InputMethodClientInfo clientInfo =
+                        mPerUserData.getClientFromIdLocked(clientId);
+                if (clientInfo == null) {
+                    Slog.e(TAG, "Unknown clientId=" + clientId);
+                    return;
+                }
+                try {
+                    clientInfo.mClient.setActive(active, false /* fullscreen */);
+                } catch (RemoteException e) {
+                    return;
+                }
+            }
+        }
     }
 
     /**