Loading core/java/android/app/SystemServiceRegistry.java +1 −1 Original line number Diff line number Diff line Loading @@ -380,7 +380,7 @@ final class SystemServiceRegistry { new StaticServiceFetcher<InputMethodManager>() { @Override public InputMethodManager createService() { return InputMethodManager.getInstance(); return InputMethodManager.getInstanceInternal(); }}); registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class, Loading core/java/android/view/WindowManagerGlobal.java +4 −5 Original line number Diff line number Diff line Loading @@ -196,11 +196,10 @@ public final class WindowManagerGlobal { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { if (InputMethodManager.ENABLE_LEGACY_EAGER_INITIALIZATION) { // Emulate the legacy behavior. The global instance of InputMethodManager // was instantiated here. InputMethodManager.getInstance(); } // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { Loading core/java/android/view/inputmethod/InputMethodManager.java +45 −12 Original line number Diff line number Diff line Loading @@ -228,12 +228,10 @@ public final class InputMethodManager { static final String PENDING_EVENT_COUNTER = "aq:imm"; /** * {@code true} if we want to instantiate {@link InputMethodManager} eagerly in * {@link android.view.WindowManagerGlobal#getWindowSession()}, which is often called in an * early stage of process startup, which is how Android has worked. * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly * or indirectly relied on {@link #sInstance} via reflection or something like that. * * <p>We still have this settings because we know there are possible compatibility concerns if * we stop doing so. Here are scenarios we know and there could be more scenarios we are not * <p>Here are scenarios we know and there could be more scenarios we are not * aware of right know.</p> * * <ul> Loading @@ -260,13 +258,22 @@ public final class InputMethodManager { * {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li> * </ul> * * <p>TODO(Bug 116157766): Check if we can set {@code false} here then remove this settings.</p> * <p>Since this is purely a compatibility hack, this method must be used only from * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p> * * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p> * @hide */ public static final boolean ENABLE_LEGACY_EAGER_INITIALIZATION = true; public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() { getInstanceInternal(); } private static final Object sLock = new Object(); /** * @deprecated This cannot be compatible with multi-display. Please do not use this. */ @Deprecated @GuardedBy("sLock") @UnsupportedAppUsage static InputMethodManager sInstance; Loading Loading @@ -735,12 +742,13 @@ public final class InputMethodManager { } /** * Retrieve the global InputMethodManager instance, creating it if it * doesn't already exist. * Retrieve the global {@link InputMethodManager} instance, creating it if it doesn't already * exist. * * @return global {@link InputMethodManager} instance * @hide */ @UnsupportedAppUsage public static InputMethodManager getInstance() { public static InputMethodManager getInstanceInternal() { synchronized (sLock) { if (sInstance == null) { try { Loading @@ -756,14 +764,39 @@ public final class InputMethodManager { } /** * Private optimization: retrieve the global InputMethodManager instance, if it exists. * Deprecated. Do not use. * * @return global {@link InputMethodManager} instance * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully * support multi-display scenario. * @hide */ @Deprecated @UnsupportedAppUsage public static InputMethodManager getInstance() { Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be" + " compatible with multi-display." + " Use context.getSystemService(InputMethodManager.class) instead.", new Throwable()); ensureDefaultInstanceForDefaultDisplayIfNecessary(); return peekInstance(); } /** * Deprecated. Do not use. * * @return {@link #sInstance} * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully * support multi-display scenario. * @hide */ @Deprecated @UnsupportedAppUsage public static InputMethodManager peekInstance() { Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be" + " compatible with multi-display." + " Use context.getSystemService(InputMethodManager.class) instead.", new Throwable()); synchronized (sLock) { return sInstance; } Loading core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * 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 static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.WindowManager; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidJUnit4.class) public class InputMethodManagerTest { @Test public void testPrivateApiGetInstance() throws Exception { final InputMethodManager globalImm = InputMethodManager.getInstance(); assertNotNull("InputMethodManager.getInstance() still needs to work due to" + " @UnsupportedAppUsage", globalImm); assertEquals("InputMethodManager.peekInstance() still needs to work due to" + " @UnsupportedAppUsage", globalImm, InputMethodManager.peekInstance()); final Context testContext = InstrumentationRegistry.getInstrumentation() .getTargetContext(); final WindowManager wm = testContext.getSystemService(WindowManager.class); final Context defaultDisplayContext = testContext.createDisplayContext(wm.getDefaultDisplay()); final InputMethodManager imm = defaultDisplayContext.getSystemService(InputMethodManager.class); assertEquals("InputMethodManager.getInstance() always returns the instance for the default" + " display.", globalImm, imm); } } Loading
core/java/android/app/SystemServiceRegistry.java +1 −1 Original line number Diff line number Diff line Loading @@ -380,7 +380,7 @@ final class SystemServiceRegistry { new StaticServiceFetcher<InputMethodManager>() { @Override public InputMethodManager createService() { return InputMethodManager.getInstance(); return InputMethodManager.getInstanceInternal(); }}); registerService(Context.TEXT_SERVICES_MANAGER_SERVICE, TextServicesManager.class, Loading
core/java/android/view/WindowManagerGlobal.java +4 −5 Original line number Diff line number Diff line Loading @@ -196,11 +196,10 @@ public final class WindowManagerGlobal { synchronized (WindowManagerGlobal.class) { if (sWindowSession == null) { try { if (InputMethodManager.ENABLE_LEGACY_EAGER_INITIALIZATION) { // Emulate the legacy behavior. The global instance of InputMethodManager // was instantiated here. InputMethodManager.getInstance(); } // TODO(b/116157766): Remove this hack after cleaning up @UnsupportedAppUsage InputMethodManager.ensureDefaultInstanceForDefaultDisplayIfNecessary(); IWindowManager windowManager = getWindowManagerService(); sWindowSession = windowManager.openSession( new IWindowSessionCallback.Stub() { Loading
core/java/android/view/inputmethod/InputMethodManager.java +45 −12 Original line number Diff line number Diff line Loading @@ -228,12 +228,10 @@ public final class InputMethodManager { static final String PENDING_EVENT_COUNTER = "aq:imm"; /** * {@code true} if we want to instantiate {@link InputMethodManager} eagerly in * {@link android.view.WindowManagerGlobal#getWindowSession()}, which is often called in an * early stage of process startup, which is how Android has worked. * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly * or indirectly relied on {@link #sInstance} via reflection or something like that. * * <p>We still have this settings because we know there are possible compatibility concerns if * we stop doing so. Here are scenarios we know and there could be more scenarios we are not * <p>Here are scenarios we know and there could be more scenarios we are not * aware of right know.</p> * * <ul> Loading @@ -260,13 +258,22 @@ public final class InputMethodManager { * {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li> * </ul> * * <p>TODO(Bug 116157766): Check if we can set {@code false} here then remove this settings.</p> * <p>Since this is purely a compatibility hack, this method must be used only from * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p> * * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p> * @hide */ public static final boolean ENABLE_LEGACY_EAGER_INITIALIZATION = true; public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() { getInstanceInternal(); } private static final Object sLock = new Object(); /** * @deprecated This cannot be compatible with multi-display. Please do not use this. */ @Deprecated @GuardedBy("sLock") @UnsupportedAppUsage static InputMethodManager sInstance; Loading Loading @@ -735,12 +742,13 @@ public final class InputMethodManager { } /** * Retrieve the global InputMethodManager instance, creating it if it * doesn't already exist. * Retrieve the global {@link InputMethodManager} instance, creating it if it doesn't already * exist. * * @return global {@link InputMethodManager} instance * @hide */ @UnsupportedAppUsage public static InputMethodManager getInstance() { public static InputMethodManager getInstanceInternal() { synchronized (sLock) { if (sInstance == null) { try { Loading @@ -756,14 +764,39 @@ public final class InputMethodManager { } /** * Private optimization: retrieve the global InputMethodManager instance, if it exists. * Deprecated. Do not use. * * @return global {@link InputMethodManager} instance * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully * support multi-display scenario. * @hide */ @Deprecated @UnsupportedAppUsage public static InputMethodManager getInstance() { Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be" + " compatible with multi-display." + " Use context.getSystemService(InputMethodManager.class) instead.", new Throwable()); ensureDefaultInstanceForDefaultDisplayIfNecessary(); return peekInstance(); } /** * Deprecated. Do not use. * * @return {@link #sInstance} * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully * support multi-display scenario. * @hide */ @Deprecated @UnsupportedAppUsage public static InputMethodManager peekInstance() { Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be" + " compatible with multi-display." + " Use context.getSystemService(InputMethodManager.class) instead.", new Throwable()); synchronized (sLock) { return sInstance; } Loading
core/tests/coretests/src/android/view/inputmethod/InputMethodManagerTest.java 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * 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 static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import android.content.Context; import android.support.test.InstrumentationRegistry; import android.support.test.filters.SmallTest; import android.support.test.runner.AndroidJUnit4; import android.view.WindowManager; import org.junit.Test; import org.junit.runner.RunWith; @SmallTest @RunWith(AndroidJUnit4.class) public class InputMethodManagerTest { @Test public void testPrivateApiGetInstance() throws Exception { final InputMethodManager globalImm = InputMethodManager.getInstance(); assertNotNull("InputMethodManager.getInstance() still needs to work due to" + " @UnsupportedAppUsage", globalImm); assertEquals("InputMethodManager.peekInstance() still needs to work due to" + " @UnsupportedAppUsage", globalImm, InputMethodManager.peekInstance()); final Context testContext = InstrumentationRegistry.getInstrumentation() .getTargetContext(); final WindowManager wm = testContext.getSystemService(WindowManager.class); final Context defaultDisplayContext = testContext.createDisplayContext(wm.getDefaultDisplay()); final InputMethodManager imm = defaultDisplayContext.getSystemService(InputMethodManager.class); assertEquals("InputMethodManager.getInstance() always returns the instance for the default" + " display.", globalImm, imm); } }