Fix for bug #34905789

A call to showInputMethodPickerFromClient should be allowed only if the
caller is:
  * The system service, as system services should have the privilege to
    show any dialogs
  * The current IME client, as it was already enabled by the user
  * The app on the foreground, as the user cannot distinguish the source
    of the request (i.e., foreground vs background app) and might be
    mislead by a background app to change settings
  * A process with the android.Manifest.permission.WRITE_SECURE_SETTINGS
    permission, as it already has the permission to change settings

Fixes: 34905789
Test: manual
Change-Id: I4f0fc21268200c64d12b31ca54416acfbf62f37b
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index bff39b3..a8e2f32 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -2788,6 +2788,27 @@
         return res;
     }
 
+    private boolean canShowInputMethodPickerLocked(IInputMethodClient client) {
+        final int uid = Binder.getCallingUid();
+        if (UserHandle.getAppId(uid) == Process.SYSTEM_UID) {
+            return true;
+        } else if (mCurClient != null && client != null
+                && mCurClient.client.asBinder() == client.asBinder()) {
+            return true;
+        } else if (mCurIntent != null && InputMethodUtils.checkIfPackageBelongsToUid(
+                mAppOpsManager,
+                uid,
+                mCurIntent.getComponent().getPackageName())) {
+            return true;
+        } else if (mContext.checkCallingPermission(
+                android.Manifest.permission.WRITE_SECURE_SETTINGS)
+                == PackageManager.PERMISSION_GRANTED) {
+            return true;
+        }
+
+        return false;
+    }
+
     @Override
     public void showInputMethodPickerFromClient(
             IInputMethodClient client, int auxiliarySubtypeMode) {
@@ -2795,10 +2816,10 @@
             return;
         }
         synchronized (mMethodMap) {
-            if (mCurClient == null || client == null
-                    || mCurClient.client.asBinder() != client.asBinder()) {
+            if(!canShowInputMethodPickerLocked(client)) {
                 Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
                         + Binder.getCallingUid() + ": " + client);
+                return;
             }
 
             // Always call subtype picker, because subtype picker is a superset of input method