Temporarily move MULTI_CLIENT_IME_ENABLED to frameworks.jar

This is a preparation to implement per-profile IME in
InputMethodManagerService (IMMS).

Multi-client IME is designed and implemented to be able to deal with
multiple profiles at the same time from its beginning [1].  This means
that when multi-client IME is enabled with system properties, it also
means that per-profile IME is enabled.

At the same time, the following classes need to change its behavior
whether per-profile IME is enabled or not.

 * android.provider.Setings
 * com.android.server.inputmethod.InputMethodManagerService
 * com.android.server.textservices.TextServicesManagerService
 * com.android.server.devicepolicy.DevicePolicyManagerService
 * com.android.server.devicepolicy.OverlayPackagesProvider

The problem is that android.provider.Setings lives in the
frameworks.jar.  Hence if we want to expose something like
PER_PROFILE_IME_ENABLED to android.provider.Setings, then such a flag
needs to live in frameworks.jar.

Note that this is expected to be a temporary change.  Once per-profile
IME becomes always enabled in IMMS, we can safely roll back this
change.

Note also that static initializer of InputMethodSystemProperty is
expected to be evaluated only once as long as
InputMethodSystemProperty is loaded before Zygote.

 [1]: I41dfe854557b178d8af740bc2869c936fc88608b
      bae5bea23cfac3769569a230b56ad85cdd000675

Bug: 120709962
Test: prebuilts/checkstyle/checkstyle.py -f \
        frameworks/base/core/java/android/view/inputmethod/InputMethodSystemProperty.java
Test: Manually verified as follows:
  1. make -j MultiClientInputMethod
  2. adb install -r $OUT/system/priv-app/MultiClientInputMethod/MultiClientInputMethod.apk
  3. adb root
  4. adb shell setprop persist.debug.multi_client_ime \
       com.example.android.multiclientinputmethod/.MultiClientInputMethod
  5. adb reboot
  6. Make sure that multi-client IME is enabled
Change-Id: Iad8aba7edb1e60ccc1ce5192a11e01b6aa8d00a0
diff --git a/core/java/android/view/inputmethod/InputMethodSystemProperty.java b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
new file mode 100644
index 0000000..b233b75
--- /dev/null
+++ b/core/java/android/view/inputmethod/InputMethodSystemProperty.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Build;
+import android.os.SystemProperties;
+
+/**
+ * Various (pseudo) constants about IME behaviors.
+ *
+ * @hide
+ */
+public class InputMethodSystemProperty {
+    /**
+     * System property key for the production use. The value must be either empty or a valid
+     * (flattened) component name of the multi-client IME.
+     */
+    private static final String PROP_PROD_MULTI_CLIENT_IME = "ro.sys.multi_client_ime";
+
+    /**
+     * System property key for debugging purpose. The value must be either empty or a valid
+     * (flattened) component name of the multi-client IME.
+     *
+     * <p>This value will be ignored when {@link Build#IS_DEBUGGABLE} returns {@code false}</p>
+     */
+    private static final String PROP_DEBUG_MULTI_CLIENT_IME = "persist.debug.multi_client_ime";
+
+    @Nullable
+    private static ComponentName getMultiClientImeComponentName() {
+        if (Build.IS_DEBUGGABLE) {
+            // If debuggable, allow developers to override the multi-client IME component name
+            // with a different (writable) key.
+            final ComponentName debugIme = ComponentName.unflattenFromString(
+                    SystemProperties.get(PROP_DEBUG_MULTI_CLIENT_IME, ""));
+            if (debugIme != null) {
+                return debugIme;
+            }
+        }
+        return ComponentName.unflattenFromString(
+                SystemProperties.get(PROP_PROD_MULTI_CLIENT_IME, ""));
+    }
+
+    /**
+     * {@link ComponentName} of multi-client IME to be used.
+     *
+     * @hide
+     */
+    @Nullable
+    public static final ComponentName sMultiClientImeComponentName =
+            getMultiClientImeComponentName();
+
+    /**
+     * {@code true} when multi-client IME is enabled.
+     *
+     * @hide
+     */
+    public static final boolean MULTI_CLIENT_IME_ENABLED = (sMultiClientImeComponentName != null);
+}
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index b098078..ffe14d9 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -50,7 +50,6 @@
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
@@ -65,6 +64,7 @@
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.inputmethod.IMultiClientInputMethod;
@@ -99,20 +99,6 @@
     static final String TAG = "MultiClientInputMethodManagerService";
     static final boolean DEBUG = false;
 
-    /**
-     * System property key for the production use. The value must be either empty or a valid
-     * (flattened) component name of the multi-client IME.
-     */
-    private static final String PROP_PROD_MULTI_CLIENT_IME = "ro.sys.multi_client_ime";
-
-    /**
-     * System property key for debugging purpose. The value must be either empty or a valid
-     * (flattened) component name of the multi-client IME.
-     *
-     * <p>This value will be ignored when {@link Build#IS_DEBUGGABLE} returns {@code false}</p>
-     */
-    private static final String PROP_DEBUG_MULTI_CLIENT_IME = "persist.debug.multi_client_ime";
-
     private static final long RECONNECT_DELAY_MSEC = 1000;
 
     /**
@@ -125,36 +111,8 @@
                     | Context.BIND_NOT_FOREGROUND
                     | Context.BIND_FOREGROUND_SERVICE;
 
-    /**
-     * Inner class to read system property on demand, not when
-     * {@link MultiClientInputMethodManagerService} class is accessed.
-     */
-    private static final class ImeComponentName {
-        private static ComponentName evaluate() {
-            if (Build.IS_DEBUGGABLE) {
-                // If debuggable, allow developers to override the multi-client IME component name
-                // with a different (writable) key.
-                final ComponentName debugIme = ComponentName.unflattenFromString(
-                        SystemProperties.get(PROP_DEBUG_MULTI_CLIENT_IME, ""));
-                if (debugIme != null) {
-                    return debugIme;
-                }
-            }
-            return ComponentName.unflattenFromString(
-                    SystemProperties.get(PROP_PROD_MULTI_CLIENT_IME, ""));
-        }
-
-        /**
-         * {@link ComponentName} of the multi-client IME.  {@code null} when the system is not
-         * configured to use multi-client IME.
-         */
-        @Nullable
-        static final ComponentName sValue = evaluate();
-    }
-
-    public static boolean isConfiguredToUse() {
-        return ImeComponentName.sValue != null;
-    }
+    private static final ComponentName sImeComponentName =
+            InputMethodSystemProperty.sMultiClientImeComponentName;
 
     private static void reportNotSupported() {
         if (DEBUG) {
@@ -270,10 +228,10 @@
                 return;
             }
 
-            final InputMethodInfo imi = queryInputMethod(mContext, userId, ImeComponentName.sValue);
+            final InputMethodInfo imi = queryInputMethod(mContext, userId, sImeComponentName);
             if (imi == null) {
                 Slog.w(TAG, "Multi-client InputMethod is not found. component="
-                        + ImeComponentName.sValue);
+                        + sImeComponentName);
                 synchronized (data.mLock) {
                     switch (data.mState) {
                         case PerUserState.USER_LOCKED:
@@ -518,9 +476,9 @@
                 return;
             }
             final String packageName = uri.getSchemeSpecificPart();
-            if (ImeComponentName.sValue == null
+            if (sImeComponentName == null
                     || packageName == null
-                    || !TextUtils.equals(ImeComponentName.sValue.getPackageName(), packageName)) {
+                    || !TextUtils.equals(sImeComponentName.getPackageName(), packageName)) {
                 return;
             }
             final int userId = UserHandle.getUserId(intent.getIntExtra(Intent.EXTRA_UID, 0));
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 046c991..1862636 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -63,6 +63,7 @@
 import android.util.Slog;
 import android.util.TimingsTraceLog;
 import android.view.WindowManager;
+import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
 import com.android.internal.logging.MetricsLogger;
@@ -1019,7 +1020,7 @@
         // Bring up services needed for UI.
         if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
             traceBeginAndSlog("StartInputMethodManagerLifecycle");
-            if (MultiClientInputMethodManagerService.isConfiguredToUse()) {
+            if (InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) {
                 mSystemServiceManager.startService(
                         MultiClientInputMethodManagerService.Lifecycle.class);
             } else {