diff options
2 files changed, 42 insertions, 36 deletions
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java index b0d734df37b4..9ac7f1b731fc 100644 --- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java +++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java @@ -88,6 +88,7 @@ import android.os.Debug; import android.os.Handler; import android.os.IBinder; import android.os.LocaleList; +import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; @@ -922,18 +923,45 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. public static final class Lifecycle extends SystemService { private final InputMethodManagerService mService; - public Lifecycle(Context context) { - this(context, new InputMethodManagerService(context, - shouldEnableConcurrentMultiUserMode(context))); + this(context, createServiceForProduction(context)); } - public Lifecycle( - Context context, @NonNull InputMethodManagerService inputMethodManagerService) { + @VisibleForTesting + Lifecycle(Context context, @NonNull InputMethodManagerService inputMethodManagerService) { super(context); mService = inputMethodManagerService; } + /** + * Does initialization then instantiate {@link InputMethodManagerService} for production + * configurations. + * + * <p>We have this abstraction just because several unit tests directly initialize + * {@link InputMethodManagerService} with some mocked/emulated dependencies.</p> + * + * @param context {@link Context} to be used to set up + * @return {@link InputMethodManagerService} object to be used + */ + @NonNull + private static InputMethodManagerService createServiceForProduction( + @NonNull Context context) { + // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading + // additional subtypes in switchUserOnHandlerLocked(). + final ServiceThread thread = new ServiceThread(HANDLER_THREAD_NAME, + Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + thread.start(); + + final ServiceThread ioThread = new ServiceThread(PACKAGE_MONITOR_THREAD_NAME, + Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + ioThread.start(); + + return new InputMethodManagerService(context, + shouldEnableConcurrentMultiUserMode(context), thread.getLooper(), + Handler.createAsync(ioThread.getLooper()), + null /* bindingControllerForTesting */); + } + @Override public void onStart() { mService.publishLocalService(); @@ -1041,17 +1069,12 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. mHandler.post(task); } - public InputMethodManagerService(Context context, - boolean concurrentMultiUserModeEnabled) { - this(context, concurrentMultiUserModeEnabled, null, null, null); - } - @VisibleForTesting InputMethodManagerService( Context context, boolean concurrentMultiUserModeEnabled, - @Nullable ServiceThread serviceThreadForTesting, - @Nullable ServiceThread ioThreadForTesting, + @NonNull Looper uiLooper, + @NonNull Handler ioHandler, @Nullable IntFunction<InputMethodBindingController> bindingControllerForTesting) { synchronized (ImfLock.class) { mConcurrentMultiUserModeEnabled = concurrentMultiUserModeEnabled; @@ -1059,28 +1082,8 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. mRes = context.getResources(); SecureSettingsWrapper.onStart(mContext); - // TODO(b/196206770): Disallow I/O on this thread. Currently it's needed for loading - // additional subtypes in switchUserOnHandlerLocked(). - final ServiceThread thread = - serviceThreadForTesting != null - ? serviceThreadForTesting - : new ServiceThread( - HANDLER_THREAD_NAME, - Process.THREAD_PRIORITY_FOREGROUND, - true /* allowIo */); - thread.start(); - mHandler = Handler.createAsync(thread.getLooper(), this); - { - final ServiceThread ioThread = - ioThreadForTesting != null - ? ioThreadForTesting - : new ServiceThread( - PACKAGE_MONITOR_THREAD_NAME, - Process.THREAD_PRIORITY_FOREGROUND, - true /* allowIo */); - ioThread.start(); - mIoHandler = Handler.createAsync(ioThread.getLooper()); - } + mHandler = Handler.createAsync(uiLooper, this); + mIoHandler = ioHandler; SystemLocaleWrapper.onStart(context, this::onActionLocaleChanged, mHandler); mImeTrackerService = new ImeTrackerService(mHandler); mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class); @@ -1128,7 +1131,7 @@ public final class InputMethodManagerService implements IInputMethodManagerImpl. mNonPreemptibleInputMethods = mRes.getStringArray( com.android.internal.R.array.config_nonPreemptibleInputMethods); Runnable discardDelegationTextRunnable = () -> discardHandwritingDelegationText(); - mHwController = new HandwritingModeController(mContext, thread.getLooper(), + mHwController = new HandwritingModeController(mContext, uiLooper, new InkWindowInitializer(), discardDelegationTextRunnable); registerDeviceListenerAndCheckStylusSupport(); } diff --git a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java index 17d9ef9fad34..ff308d9952f9 100644 --- a/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java +++ b/services/tests/InputMethodSystemServerTests/src/com/android/server/inputmethod/InputMethodManagerServiceTestBase.java @@ -41,6 +41,7 @@ import android.content.res.Configuration; import android.hardware.input.IInputManager; import android.hardware.input.InputManagerGlobal; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.Process; import android.os.RemoteException; @@ -227,14 +228,16 @@ public class InputMethodManagerServiceTestBase { "immstest1", Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + mServiceThread.start(); mIoThread = new ServiceThread( "immstest2", Process.THREAD_PRIORITY_FOREGROUND, true /* allowIo */); + mIoThread.start(); mInputMethodManagerService = new InputMethodManagerService(mContext, InputMethodManagerService.shouldEnableConcurrentMultiUserMode(mContext), - mServiceThread, mIoThread, + mServiceThread.getLooper(), Handler.createAsync(mIoThread.getLooper()), unusedUserId -> mMockInputMethodBindingController); spyOn(mInputMethodManagerService); |