Enable default system IMEs for system user

Added GET_DEFAULT_IMES flag to AppsQueryHelper. Default system IMEs are now
enabled for system user.

Bug: 25276229
Change-Id: I38d74903951200e2207e1864bb3a815f8f2d572f
diff --git a/core/java/android/content/pm/AppsQueryHelper.java b/core/java/android/content/pm/AppsQueryHelper.java
index 56b3173..a5a8e3f 100644
--- a/core/java/android/content/pm/AppsQueryHelper.java
+++ b/core/java/android/content/pm/AppsQueryHelper.java
@@ -23,6 +23,8 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArraySet;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -46,6 +48,14 @@
      */
     public static int GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM = 1 << 1;
 
+    /**
+     * Return all input methods that are marked as default.
+     * <p>When this flag is set, {@code user} specified in
+     * {@link #queryApps(int, boolean, UserHandle)} must be
+     * {@link UserHandle#myUserId user of the current process}.
+     */
+    public static int GET_DEFAULT_IMES = 1 << 2;
+
     private final Context mContext;
     private List<ApplicationInfo> mAllApps;
 
@@ -56,13 +66,14 @@
     /**
      * Return a List of all packages that satisfy a specified criteria.
      * @param flags search flags. Use any combination of {@link #GET_NON_LAUNCHABLE_APPS},
-     * {@link #GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM}
+     * {@link #GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM} or {@link #GET_DEFAULT_IMES}.
      * @param systemAppsOnly if true, only system apps will be returned
      * @param user user, whose apps are queried
      */
     public List<String> queryApps(int flags, boolean systemAppsOnly, UserHandle user) {
         boolean nonLaunchableApps = (flags & GET_NON_LAUNCHABLE_APPS) > 0;
         boolean interactAcrossUsers = (flags & GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM) > 0;
+        boolean defaultImes = (flags & GET_DEFAULT_IMES) > 0;
         if (mAllApps == null) {
             mAllApps = getAllApps(user.getIdentifier());
         }
@@ -118,6 +129,33 @@
             }
         }
 
+        if (defaultImes) {
+            if (UserHandle.myUserId() != user.getIdentifier()) {
+                throw new IllegalArgumentException("Specified user handle " + user
+                        + " is not a user of the current process.");
+            }
+            List<InputMethodInfo> imis = getInputMethodList();
+            int imisSize = imis.size();
+            ArraySet<String> defaultImePackages = new ArraySet<>();
+            for (int i = 0; i < imisSize; i++) {
+                InputMethodInfo imi = imis.get(i);
+                if (imi.isDefault(mContext)) {
+                    defaultImePackages.add(imi.getPackageName());
+                }
+            }
+            final int allAppsSize = mAllApps.size();
+            for (int i = 0; i < allAppsSize; i++) {
+                final ApplicationInfo appInfo = mAllApps.get(i);
+                if (systemAppsOnly && !appInfo.isSystemApp()) {
+                    continue;
+                }
+                final String packageName = appInfo.packageName;
+                if (defaultImePackages.contains(packageName)) {
+                    result.add(packageName);
+                }
+            }
+        }
+
         return result;
     }
 
@@ -150,4 +188,12 @@
             throw new IllegalStateException("Package manager has died", e);
         }
     }
+
+    @VisibleForTesting
+    @SuppressWarnings("unchecked")
+    protected List<InputMethodInfo> getInputMethodList() {
+        InputMethodManager imm = (InputMethodManager)
+                mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
+        return imm.getInputMethodList();
+    }
 }
diff --git a/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
index 80181cf..4c9b00a 100644
--- a/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
+++ b/core/tests/coretests/src/android/content/pm/AppsQueryHelperTests.java
@@ -20,6 +20,7 @@
 import android.content.Intent;
 import android.os.UserHandle;
 import android.test.AndroidTestCase;
+import android.view.inputmethod.InputMethodInfo;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -77,6 +78,27 @@
         assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "sys_app3"), apps);
     }
 
+    public void testQueryAppsDefaultIme() {
+        // Test query default system IMEs
+        List<String> apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_DEFAULT_IMES,
+                true, UserHandle.of(UserHandle.myUserId()));
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1"), apps);
+
+        // Test query default IMEs
+        apps = mAppsQueryHelper.queryApps(AppsQueryHelper.GET_DEFAULT_IMES, false,
+                UserHandle.of(UserHandle.myUserId()));
+        assertEqualsIgnoreOrder(Arrays.asList("sys_app1", "app4"), apps);
+
+        // Test that GET_DEFAULT_IMES cannot be used with a user id different from current process
+        try {
+            mAppsQueryHelper.queryApps(AppsQueryHelper.GET_DEFAULT_IMES, false,
+                    UserHandle.of(UserHandle.USER_NULL));
+            fail("queryApps must fail if wrong user was passed");
+        } catch (IllegalArgumentException e) {
+            // OK
+        }
+    }
+
     private class AppsQueryHelperTestable extends AppsQueryHelper {
 
         public AppsQueryHelperTestable(Context context) {
@@ -121,6 +143,21 @@
             p1.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
             return Arrays.asList(p1);
         }
+
+        @Override
+        protected List<InputMethodInfo> getInputMethodList() {
+            final ResolveInfo sysApp1 = new ResolveInfo();
+            sysApp1.serviceInfo = new ServiceInfo();
+            sysApp1.serviceInfo.packageName = "sys_app1";
+            sysApp1.serviceInfo.name = "name";
+            InputMethodInfo imi1 = new InputMethodInfo(sysApp1, false, null, null, 0, true);
+            final ResolveInfo app4 = new ResolveInfo();
+            app4.serviceInfo = new ServiceInfo();
+            app4.serviceInfo.packageName = "app4";
+            app4.serviceInfo.name = "name";
+            InputMethodInfo imi2 = new InputMethodInfo(app4, false, null, null, 0, true);
+            return Arrays.asList(imi1, imi2);
+        }
     }
 
     private static void assertEqualsIgnoreOrder(List<String> expected, List<String> actual) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9834757..80cb4d0 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -12089,7 +12089,8 @@
             AppsQueryHelper queryHelper = new AppsQueryHelper(mContext);
             Set<String> enableApps = new HashSet<>();
             enableApps.addAll(queryHelper.queryApps(AppsQueryHelper.GET_NON_LAUNCHABLE_APPS
-                            | AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM,
+                            | AppsQueryHelper.GET_APPS_WITH_INTERACT_ACROSS_USERS_PERM
+                            | AppsQueryHelper.GET_DEFAULT_IMES,
                             /* systemAppsOnly */ true, UserHandle.SYSTEM));
             ArraySet<String> wlApps = SystemConfig.getInstance().getSystemUserWhitelistedApps();
             enableApps.addAll(wlApps);