Verify that EditorInfo.packageName and uid are consistent

Currently EditorInfo.packageName is filled in the application
process and passed to the IME without any verification.

With this CL, the system makes sure that the provided package
name and application's uid are consistent before establishing
the input connection.  In other words, the risk of spoofed
EditorInfo.packageName will be mitigated with this change.

This should be beneficial especially when an IME wants to have
per-application settings and/or dictionaries.

Bug: 18931038

Change-Id: Ib871141e3381e45c2623c5f4d692da7a7e78fcc5
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 4677f65..d92a89f 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -15,6 +15,7 @@
 
 package com.android.server;
 
+import android.annotation.NonNull;
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
 import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
@@ -1285,13 +1286,24 @@
         return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
     }
 
-    InputBindResult startInputUncheckedLocked(ClientState cs,
+    InputBindResult startInputUncheckedLocked(@NonNull ClientState cs,
             IInputContext inputContext, EditorInfo attribute, int controlFlags) {
         // If no method is currently selected, do nothing.
         if (mCurMethodId == null) {
             return mNoBinding;
         }
 
+        if (attribute != null) {
+            // We accept an empty package name as a valid data.
+            if (!TextUtils.isEmpty(attribute.packageName) &&
+                    !InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid,
+                            attribute.packageName)) {
+                Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
+                        + " uid=" + cs.uid + " package=" + attribute.packageName);
+                return mNoBinding;
+            }
+        }
+
         if (mCurClient != cs) {
             // Was the keyguard locked when switching over to the new client?
             mCurClientInKeyguard = isKeyguardLocked();
@@ -1855,16 +1867,10 @@
         }
 
         if (mCurClient != null && mCurAttribute != null) {
-            final int uid = mCurClient.uid;
-            final String packageName = mCurAttribute.packageName;
-            if (SystemConfig.getInstance().getFixedImeApps().contains(packageName)) {
-                if (InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, uid, packageName)) {
-                    return;
-                }
-                // TODO: Do we need to lock the input method when the application reported an
-                // incorrect package name?
-                Slog.e(TAG, "Ignoring FixedImeApps due to the validation failure. uid=" + uid
-                        + " package=" + packageName);
+            // We have already made sure that the package name belongs to the application's UID.
+            // No further UID check is required.
+            if (SystemConfig.getInstance().getFixedImeApps().contains(mCurAttribute.packageName)) {
+                return;
             }
         }
 
@@ -2148,7 +2154,7 @@
                 // more quickly (not get stuck behind it initializing itself for the
                 // new focused input, even if its window wants to hide the IME).
                 boolean didStart = false;
-                        
+
                 switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
                     case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
                         if (!isTextEditor || !doAutoShow) {