Merge "Merge IInputMethodManagerInvoker and IInputMethodManagerGlobalInvoker"
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
index e32c6aa..aeff37c 100644
--- a/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
+++ b/core/java/android/view/inputmethod/IInputMethodManagerGlobalInvoker.java
@@ -17,16 +17,32 @@
 package android.view.inputmethod;
 
 import android.annotation.AnyThread;
+import android.annotation.DurationMillisLong;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresNoPermission;
 import android.annotation.RequiresPermission;
+import android.annotation.UserIdInt;
 import android.content.Context;
+import android.os.IBinder;
 import android.os.RemoteException;
+import android.os.ResultReceiver;
 import android.os.ServiceManager;
+import android.view.WindowManager;
+import android.window.ImeOnBackInvokedDispatcher;
 
+import com.android.internal.inputmethod.DirectBootAwareness;
+import com.android.internal.inputmethod.IInputMethodClient;
+import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
+import com.android.internal.inputmethod.IRemoteInputConnection;
+import com.android.internal.inputmethod.InputBindResult;
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+import com.android.internal.inputmethod.StartInputFlags;
+import com.android.internal.inputmethod.StartInputReason;
 import com.android.internal.view.IInputMethodManager;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Consumer;
 
 /**
@@ -54,9 +70,12 @@
 
     @AnyThread
     @Nullable
-    private static IInputMethodManager getService() {
+    static IInputMethodManager getService() {
         IInputMethodManager service = sServiceCache;
         if (service == null) {
+            if (InputMethodManager.isInEditModeInternal()) {
+                return null;
+            }
             service = IInputMethodManager.Stub.asInterface(
                     ServiceManager.getService(Context.INPUT_METHOD_SERVICE));
             if (service == null) {
@@ -175,4 +194,322 @@
             handleRemoteExceptionOrRethrow(e, exceptionHandler);
         }
     }
+
+    @AnyThread
+    static void addClient(@NonNull IInputMethodClient client,
+            @NonNull IRemoteInputConnection fallbackInputConnection, int untrustedDisplayId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.addClient(client, fallbackInputConnection, untrustedDisplayId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    @NonNull
+    static List<InputMethodInfo> getInputMethodList(@UserIdInt int userId,
+            @DirectBootAwareness int directBootAwareness) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return new ArrayList<>();
+        }
+        try {
+            return service.getInputMethodList(userId, directBootAwareness);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    @NonNull
+    static List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return new ArrayList<>();
+        }
+        try {
+            return service.getEnabledInputMethodList(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    @NonNull
+    static List<InputMethodSubtype> getEnabledInputMethodSubtypeList(@Nullable String imiId,
+            boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return new ArrayList<>();
+        }
+        try {
+            return service.getEnabledInputMethodSubtypeList(imiId,
+                    allowsImplicitlyEnabledSubtypes, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    @Nullable
+    static InputMethodSubtype getLastInputMethodSubtype(@UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return null;
+        }
+        try {
+            return service.getLastInputMethodSubtype(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static boolean showSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
+            int flags, int lastClickToolType, @Nullable ResultReceiver resultReceiver,
+            @SoftInputShowHideReason int reason) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return false;
+        }
+        try {
+            return service.showSoftInput(
+                    client, windowToken, flags, lastClickToolType, resultReceiver, reason);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
+            int flags, @Nullable ResultReceiver resultReceiver,
+            @SoftInputShowHideReason int reason) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return false;
+        }
+        try {
+            return service.hideSoftInput(client, windowToken, flags, resultReceiver, reason);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    @NonNull
+    static InputBindResult startInputOrWindowGainedFocus(@StartInputReason int startInputReason,
+            @NonNull IInputMethodClient client, @Nullable IBinder windowToken,
+            @StartInputFlags int startInputFlags,
+            @WindowManager.LayoutParams.SoftInputModeFlags int softInputMode,
+            @WindowManager.LayoutParams.Flags int windowFlags, @Nullable EditorInfo editorInfo,
+            @Nullable IRemoteInputConnection remoteInputConnection,
+            @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
+            int unverifiedTargetSdkVersion, @UserIdInt int userId,
+            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return InputBindResult.NULL;
+        }
+        try {
+            return service.startInputOrWindowGainedFocus(startInputReason, client, windowToken,
+                    startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection,
+                    remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId,
+                    imeDispatcher);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void showInputMethodPickerFromClient(@NonNull IInputMethodClient client,
+            int auxiliarySubtypeMode) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.showInputMethodPickerFromClient(client, auxiliarySubtypeMode);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void showInputMethodPickerFromSystem(@NonNull IInputMethodClient client,
+            int auxiliarySubtypeMode, int displayId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.showInputMethodPickerFromSystem(client, auxiliarySubtypeMode, displayId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static boolean isInputMethodPickerShownForTest() {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return false;
+        }
+        try {
+            return service.isInputMethodPickerShownForTest();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    @Nullable
+    static InputMethodSubtype getCurrentInputMethodSubtype(@UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return null;
+        }
+        try {
+            return service.getCurrentInputMethodSubtype(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void setAdditionalInputMethodSubtypes(@NonNull String imeId,
+            @NonNull InputMethodSubtype[] subtypes, @UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.setAdditionalInputMethodSubtypes(imeId, subtypes, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void setExplicitlyEnabledInputMethodSubtypes(@NonNull String imeId,
+            @NonNull int[] subtypeHashCodes, @UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.setExplicitlyEnabledInputMethodSubtypes(imeId, subtypeHashCodes, userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return 0;
+        }
+        try {
+            return service.getInputMethodWindowVisibleHeight(client);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void reportVirtualDisplayGeometryAsync(@NonNull IInputMethodClient client,
+            int childDisplayId, @Nullable float[] matrixValues) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.reportVirtualDisplayGeometryAsync(client, childDisplayId, matrixValues);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void reportPerceptibleAsync(@NonNull IBinder windowToken, boolean perceptible) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.reportPerceptibleAsync(windowToken, perceptible);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void removeImeSurfaceFromWindowAsync(@NonNull IBinder windowToken) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.removeImeSurfaceFromWindowAsync(windowToken);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void startStylusHandwriting(@NonNull IInputMethodClient client) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.startStylusHandwriting(client);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return false;
+        }
+        try {
+            return service.isStylusHandwritingAvailableAsUser(userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void addVirtualStylusIdForTestSession(IInputMethodClient client) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.addVirtualStylusIdForTestSession(client);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @AnyThread
+    static void setStylusWindowIdleTimeoutForTest(
+            IInputMethodClient client, @DurationMillisLong long timeout) {
+        final IInputMethodManager service = getService();
+        if (service == null) {
+            return;
+        }
+        try {
+            service.setStylusWindowIdleTimeoutForTest(client, timeout);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java b/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java
deleted file mode 100644
index 01e8b34..0000000
--- a/core/java/android/view/inputmethod/IInputMethodManagerInvoker.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * Copyright (C) 2022 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.AnyThread;
-import android.annotation.DurationMillisLong;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.UserIdInt;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.os.ResultReceiver;
-import android.view.WindowManager;
-import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-import android.window.ImeOnBackInvokedDispatcher;
-
-import com.android.internal.inputmethod.DirectBootAwareness;
-import com.android.internal.inputmethod.IInputMethodClient;
-import com.android.internal.inputmethod.IRemoteAccessibilityInputConnection;
-import com.android.internal.inputmethod.IRemoteInputConnection;
-import com.android.internal.inputmethod.InputBindResult;
-import com.android.internal.inputmethod.SoftInputShowHideReason;
-import com.android.internal.inputmethod.StartInputFlags;
-import com.android.internal.inputmethod.StartInputReason;
-import com.android.internal.view.IInputMethodManager;
-
-import java.util.List;
-
-/**
- * A wrapper class to invoke IPCs defined in {@link IInputMethodManager}.
- */
-final class IInputMethodManagerInvoker {
-    @NonNull
-    private final IInputMethodManager mTarget;
-
-    private IInputMethodManagerInvoker(@NonNull IInputMethodManager target) {
-        mTarget = target;
-    }
-
-    @AnyThread
-    @NonNull
-    static IInputMethodManagerInvoker create(@NonNull IInputMethodManager imm) {
-        return new IInputMethodManagerInvoker(imm);
-    }
-
-    @AnyThread
-    void addClient(@NonNull IInputMethodClient client,
-            @NonNull IRemoteInputConnection fallbackInputConnection, int untrustedDisplayId) {
-        try {
-            mTarget.addClient(client, fallbackInputConnection, untrustedDisplayId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    @NonNull
-    List<InputMethodInfo> getInputMethodList(@UserIdInt int userId,
-            @DirectBootAwareness int directBootAwareness) {
-        try {
-            return mTarget.getInputMethodList(userId, directBootAwareness);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    @NonNull
-    List<InputMethodInfo> getEnabledInputMethodList(@UserIdInt int userId) {
-        try {
-            return mTarget.getEnabledInputMethodList(userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    @NonNull
-    List<InputMethodSubtype> getEnabledInputMethodSubtypeList(@Nullable String imiId,
-            boolean allowsImplicitlyEnabledSubtypes, @UserIdInt int userId) {
-        try {
-            return mTarget.getEnabledInputMethodSubtypeList(imiId,
-                    allowsImplicitlyEnabledSubtypes, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    @Nullable
-    InputMethodSubtype getLastInputMethodSubtype(@UserIdInt int userId) {
-        try {
-            return mTarget.getLastInputMethodSubtype(userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    boolean showSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
-            int flags, int lastClickToolType, @Nullable ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason) {
-        try {
-            return mTarget.showSoftInput(
-                    client, windowToken, flags, lastClickToolType, resultReceiver, reason);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    boolean hideSoftInput(@NonNull IInputMethodClient client, @Nullable IBinder windowToken,
-            int flags, @Nullable ResultReceiver resultReceiver,
-            @SoftInputShowHideReason int reason) {
-        try {
-            return mTarget.hideSoftInput(client, windowToken, flags, resultReceiver, reason);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    @NonNull
-    InputBindResult startInputOrWindowGainedFocus(@StartInputReason int startInputReason,
-            @NonNull IInputMethodClient client, @Nullable IBinder windowToken,
-            @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
-            @WindowManager.LayoutParams.Flags int windowFlags, @Nullable EditorInfo editorInfo,
-            @Nullable IRemoteInputConnection remoteInputConnection,
-            @Nullable IRemoteAccessibilityInputConnection remoteAccessibilityInputConnection,
-            int unverifiedTargetSdkVersion, @UserIdInt int userId,
-            @NonNull ImeOnBackInvokedDispatcher imeDispatcher) {
-        try {
-            return mTarget.startInputOrWindowGainedFocus(startInputReason, client, windowToken,
-                    startInputFlags, softInputMode, windowFlags, editorInfo, remoteInputConnection,
-                    remoteAccessibilityInputConnection, unverifiedTargetSdkVersion, userId,
-                    imeDispatcher);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void showInputMethodPickerFromClient(@NonNull IInputMethodClient client,
-            int auxiliarySubtypeMode) {
-        try {
-            mTarget.showInputMethodPickerFromClient(client, auxiliarySubtypeMode);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void showInputMethodPickerFromSystem(@NonNull IInputMethodClient client,
-            int auxiliarySubtypeMode, int displayId) {
-        try {
-            mTarget.showInputMethodPickerFromSystem(client, auxiliarySubtypeMode, displayId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    boolean isInputMethodPickerShownForTest() {
-        try {
-            return mTarget.isInputMethodPickerShownForTest();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    @Nullable
-    InputMethodSubtype getCurrentInputMethodSubtype(@UserIdInt int userId) {
-        try {
-            return mTarget.getCurrentInputMethodSubtype(userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void setAdditionalInputMethodSubtypes(@NonNull String imeId,
-            @NonNull InputMethodSubtype[] subtypes, @UserIdInt int userId) {
-        try {
-            mTarget.setAdditionalInputMethodSubtypes(imeId, subtypes, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void setExplicitlyEnabledInputMethodSubtypes(@NonNull String imeId,
-            @NonNull int[] subtypeHashCodes, @UserIdInt int userId) {
-        try {
-            mTarget.setExplicitlyEnabledInputMethodSubtypes(imeId, subtypeHashCodes, userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
-        try {
-            return mTarget.getInputMethodWindowVisibleHeight(client);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void reportVirtualDisplayGeometryAsync(@NonNull IInputMethodClient client, int childDisplayId,
-            @Nullable float[] matrixValues) {
-        try {
-            mTarget.reportVirtualDisplayGeometryAsync(client, childDisplayId, matrixValues);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void reportPerceptibleAsync(@NonNull IBinder windowToken, boolean perceptible) {
-        try {
-            mTarget.reportPerceptibleAsync(windowToken, perceptible);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void removeImeSurfaceFromWindowAsync(@NonNull IBinder windowToken) {
-        try {
-            mTarget.removeImeSurfaceFromWindowAsync(windowToken);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void startStylusHandwriting(@NonNull IInputMethodClient client) {
-        try {
-            mTarget.startStylusHandwriting(client);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    boolean isStylusHandwritingAvailableAsUser(@UserIdInt int userId) {
-        try {
-            return mTarget.isStylusHandwritingAvailableAsUser(userId);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void addVirtualStylusIdForTestSession(IInputMethodClient client) {
-        try {
-            mTarget.addVirtualStylusIdForTestSession(client);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-
-    @AnyThread
-    void setStylusWindowIdleTimeoutForTest(
-            IInputMethodClient client, @DurationMillisLong long timeout) {
-        try {
-            mTarget.setStylusWindowIdleTimeoutForTest(client, timeout);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-    }
-}
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 69eed0a..53d77e1 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -70,8 +70,6 @@
 import android.os.Message;
 import android.os.Process;
 import android.os.ResultReceiver;
-import android.os.ServiceManager;
-import android.os.ServiceManager.ServiceNotFoundException;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
@@ -295,7 +293,7 @@
     private static final String SUBTYPE_MODE_VOICE = "voice";
 
     /**
-     * Provide this to {@link IInputMethodManagerInvoker#startInputOrWindowGainedFocus(int,
+     * Provide this to {@link IInputMethodManagerGlobalInvoker#startInputOrWindowGainedFocus(int,
      * IInputMethodClient, IBinder, int, int, int, EditorInfo,
      * com.android.internal.inputmethod.IRemoteInputConnection, IRemoteAccessibilityInputConnection,
      * int, int, ImeOnBackInvokedDispatcher)} to receive
@@ -422,16 +420,13 @@
             SystemProperties.getBoolean("debug.imm.optimize_noneditable_views", true);
 
     /**
-     * @deprecated Use {@link #mServiceInvoker} instead.
+     * @deprecated Use {@link IInputMethodManagerGlobalInvoker} instead.
      */
     @Deprecated
     @UnsupportedAppUsage
     final IInputMethodManager mService;
     private final Looper mMainLooper;
 
-    @NonNull
-    private final IInputMethodManagerInvoker mServiceInvoker;
-
     // For scheduling work on the main thread.  This also serves as our
     // global lock.
     // Remark on @UnsupportedAppUsage: there were context leaks on old versions
@@ -735,7 +730,7 @@
      * @hide
      */
     public void reportPerceptible(@NonNull IBinder windowToken, boolean perceptible) {
-        mServiceInvoker.reportPerceptibleAsync(windowToken, perceptible);
+        IInputMethodManagerGlobalInvoker.reportPerceptibleAsync(windowToken, perceptible);
     }
 
     private final class DelegateImpl implements
@@ -808,7 +803,7 @@
                 }
 
                 // ignore the result
-                mServiceInvoker.startInputOrWindowGainedFocus(
+                IInputMethodManagerGlobalInvoker.startInputOrWindowGainedFocus(
                         StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
                         viewForWindowFocus.getWindowToken(), startInputFlags, softInputMode,
                         windowFlags,
@@ -1353,6 +1348,10 @@
         return false;
     }
 
+    static boolean isInEditModeInternal() {
+        return isInEditMode();
+    }
+
     @NonNull
     private static InputMethodManager createInstance(int displayId, Looper looper) {
         return isInEditMode() ? createStubInstance(displayId, looper)
@@ -1361,12 +1360,9 @@
 
     @NonNull
     private static InputMethodManager createRealInstance(int displayId, Looper looper) {
-        final IInputMethodManager service;
-        try {
-            service = IInputMethodManager.Stub.asInterface(
-                    ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
-        } catch (ServiceNotFoundException e) {
-            throw new IllegalStateException(e);
+        final IInputMethodManager service = IInputMethodManagerGlobalInvoker.getService();
+        if (service == null) {
+            throw new IllegalStateException("IInputMethodManager is not available");
         }
         final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
         // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
@@ -1378,7 +1374,8 @@
         // 1) doing so has no effect for A and 2) doing so is sufficient for B.
         final long identity = Binder.clearCallingIdentity();
         try {
-            imm.mServiceInvoker.addClient(imm.mClient, imm.mFallbackInputConnection, displayId);
+            IInputMethodManagerGlobalInvoker.addClient(imm.mClient, imm.mFallbackInputConnection,
+                    displayId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -1418,7 +1415,6 @@
 
     private InputMethodManager(@NonNull IInputMethodManager service, int displayId, Looper looper) {
         mService = service;  // For @UnsupportedAppUsage
-        mServiceInvoker = IInputMethodManagerInvoker.create(service);
         mMainLooper = looper;
         mH = new H(looper);
         mDisplayId = displayId;
@@ -1512,7 +1508,8 @@
         // We intentionally do not use UserHandle.getCallingUserId() here because for system
         // services InputMethodManagerInternal.getInputMethodListAsUser() should be used
         // instead.
-        return mServiceInvoker.getInputMethodList(UserHandle.myUserId(), DirectBootAwareness.AUTO);
+        return IInputMethodManagerGlobalInvoker.getInputMethodList(UserHandle.myUserId(),
+                DirectBootAwareness.AUTO);
     }
 
     /**
@@ -1546,7 +1543,7 @@
             }
             return false;
         }
-        return mServiceInvoker.isStylusHandwritingAvailableAsUser(userId);
+        return IInputMethodManagerGlobalInvoker.isStylusHandwritingAvailableAsUser(userId);
     }
 
     /**
@@ -1560,7 +1557,8 @@
     @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
     @NonNull
     public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
-        return mServiceInvoker.getInputMethodList(userId, DirectBootAwareness.AUTO);
+        return IInputMethodManagerGlobalInvoker.getInputMethodList(userId,
+                DirectBootAwareness.AUTO);
     }
 
     /**
@@ -1576,7 +1574,7 @@
     @NonNull
     public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId,
             @DirectBootAwareness int directBootAwareness) {
-        return mServiceInvoker.getInputMethodList(userId, directBootAwareness);
+        return IInputMethodManagerGlobalInvoker.getInputMethodList(userId, directBootAwareness);
     }
 
     /**
@@ -1591,7 +1589,7 @@
         // We intentionally do not use UserHandle.getCallingUserId() here because for system
         // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used
         // instead.
-        return mServiceInvoker.getEnabledInputMethodList(UserHandle.myUserId());
+        return IInputMethodManagerGlobalInvoker.getEnabledInputMethodList(UserHandle.myUserId());
     }
 
     /**
@@ -1603,7 +1601,7 @@
      */
     @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
     public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
-        return mServiceInvoker.getEnabledInputMethodList(userId);
+        return IInputMethodManagerGlobalInvoker.getEnabledInputMethodList(userId);
     }
 
     /**
@@ -1620,7 +1618,7 @@
     @NonNull
     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(@Nullable InputMethodInfo imi,
             boolean allowsImplicitlyEnabledSubtypes) {
-        return mServiceInvoker.getEnabledInputMethodSubtypeList(
+        return IInputMethodManagerGlobalInvoker.getEnabledInputMethodSubtypeList(
                 imi == null ? null : imi.getId(),
                 allowsImplicitlyEnabledSubtypes,
                 UserHandle.myUserId());
@@ -2003,7 +2001,7 @@
             mH.executeOrSendMessage(Message.obtain(mH, MSG_ON_SHOW_REQUESTED));
             Log.d(TAG, "showSoftInput() view=" + view + " flags=" + flags + " reason="
                     + InputMethodDebug.softInputDisplayReasonToString(reason));
-            return mServiceInvoker.showSoftInput(
+            return IInputMethodManagerGlobalInvoker.showSoftInput(
                     mClient,
                     view.getWindowToken(),
                     flags,
@@ -2035,7 +2033,7 @@
             // Makes sure to call ImeInsetsSourceConsumer#onShowRequested on the UI thread.
             // TODO(b/229426865): call WindowInsetsController#show instead.
             mH.executeOrSendMessage(Message.obtain(mH, MSG_ON_SHOW_REQUESTED));
-            mServiceInvoker.showSoftInput(
+            IInputMethodManagerGlobalInvoker.showSoftInput(
                     mClient,
                     mCurRootView.getView().getWindowToken(),
                     flags,
@@ -2116,8 +2114,8 @@
                 return false;
             }
 
-            return mServiceInvoker.hideSoftInput(mClient, windowToken, flags, resultReceiver,
-                    reason);
+            return IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, flags,
+                    resultReceiver, reason);
         }
     }
 
@@ -2165,7 +2163,7 @@
                 return;
             }
 
-            mServiceInvoker.startStylusHandwriting(mClient);
+            IInputMethodManagerGlobalInvoker.startStylusHandwriting(mClient);
             // TODO(b/210039666): do we need any extra work for supporting non-native
             //   UI toolkits?
         }
@@ -2498,7 +2496,7 @@
             }
             final int targetUserId = editorInfo.targetInputMethodUser != null
                     ? editorInfo.targetInputMethodUser.getIdentifier() : UserHandle.myUserId();
-            res = mServiceInvoker.startInputOrWindowGainedFocus(
+            res = IInputMethodManagerGlobalInvoker.startInputOrWindowGainedFocus(
                     startInputReason, mClient, windowGainingFocus, startInputFlags,
                     softInputMode, windowFlags, editorInfo, servedInputConnection,
                     servedInputConnection == null ? null
@@ -2594,7 +2592,7 @@
     @TestApi
     public void addVirtualStylusIdForTestSession() {
         synchronized (mH) {
-            mServiceInvoker.addVirtualStylusIdForTestSession(mClient);
+            IInputMethodManagerGlobalInvoker.addVirtualStylusIdForTestSession(mClient);
         }
     }
 
@@ -2608,7 +2606,7 @@
     @TestApi
     public void setStylusWindowIdleTimeoutForTest(@DurationMillisLong long timeout) {
         synchronized (mH) {
-            mServiceInvoker.setStylusWindowIdleTimeoutForTest(mClient, timeout);
+            IInputMethodManagerGlobalInvoker.setStylusWindowIdleTimeoutForTest(mClient, timeout);
         }
     }
 
@@ -2745,7 +2743,7 @@
                 Log.w(TAG, "No current root view, ignoring closeCurrentInput()");
                 return;
             }
-            mServiceInvoker.hideSoftInput(
+            IInputMethodManagerGlobalInvoker.hideSoftInput(
                     mClient,
                     mCurRootView.getView().getWindowToken(),
                     HIDE_NOT_ALWAYS,
@@ -2821,7 +2819,7 @@
         synchronized (mH) {
             if (isImeSessionAvailableLocked() && mCurRootView != null
                     && mCurRootView.getWindowToken() == windowToken) {
-                mServiceInvoker.hideSoftInput(mClient, windowToken, 0 /* flags */,
+                IInputMethodManagerGlobalInvoker.hideSoftInput(mClient, windowToken, 0 /* flags */,
                         null /* resultReceiver */,
                         SoftInputShowHideReason.HIDE_SOFT_INPUT_BY_INSETS_API);
             }
@@ -2835,7 +2833,7 @@
      */
     public void removeImeSurface(@NonNull IBinder windowToken) {
         synchronized (mH) {
-            mServiceInvoker.removeImeSurfaceFromWindowAsync(windowToken);
+            IInputMethodManagerGlobalInvoker.removeImeSurfaceFromWindowAsync(windowToken);
         }
     }
 
@@ -3440,12 +3438,13 @@
         final int mode = showAuxiliarySubtypes
                 ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
                 : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
-        mServiceInvoker.showInputMethodPickerFromSystem(mClient, mode, displayId);
+        IInputMethodManagerGlobalInvoker.showInputMethodPickerFromSystem(mClient, mode, displayId);
     }
 
     @GuardedBy("mH")
     private void showInputMethodPickerLocked() {
-        mServiceInvoker.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
+        IInputMethodManagerGlobalInvoker.showInputMethodPickerFromClient(mClient,
+                SHOW_IM_PICKER_MODE_AUTO);
     }
 
     /**
@@ -3461,7 +3460,7 @@
      */
     @TestApi
     public boolean isInputMethodPickerShown() {
-        return mServiceInvoker.isInputMethodPickerShownForTest();
+        return IInputMethodManagerGlobalInvoker.isInputMethodPickerShownForTest();
     }
 
     /**
@@ -3500,7 +3499,7 @@
      */
     @Nullable
     public InputMethodSubtype getCurrentInputMethodSubtype() {
-        return mServiceInvoker.getCurrentInputMethodSubtype(UserHandle.myUserId());
+        return IInputMethodManagerGlobalInvoker.getCurrentInputMethodSubtype(UserHandle.myUserId());
     }
 
     /**
@@ -3545,7 +3544,7 @@
             return false;
         }
         final List<InputMethodSubtype> enabledSubtypes =
-                mServiceInvoker.getEnabledInputMethodSubtypeList(imeId, true,
+                IInputMethodManagerGlobalInvoker.getEnabledInputMethodSubtypeList(imeId, true,
                         UserHandle.myUserId());
         final int numSubtypes = enabledSubtypes.size();
         for (int i = 0; i < numSubtypes; ++i) {
@@ -3611,7 +3610,7 @@
     @UnsupportedAppUsage(trackingBug = 204906124, maxTargetSdk = Build.VERSION_CODES.TIRAMISU,
             publicAlternatives = "Use {@link android.view.WindowInsets} instead")
     public int getInputMethodWindowVisibleHeight() {
-        return mServiceInvoker.getInputMethodWindowVisibleHeight(mClient);
+        return IInputMethodManagerGlobalInvoker.getInputMethodWindowVisibleHeight(mClient);
     }
 
     /**
@@ -3631,7 +3630,8 @@
             matrixValues = new float[9];
             matrix.getValues(matrixValues);
         }
-        mServiceInvoker.reportVirtualDisplayGeometryAsync(mClient, childDisplayId, matrixValues);
+        IInputMethodManagerGlobalInvoker.reportVirtualDisplayGeometryAsync(mClient, childDisplayId,
+                matrixValues);
     }
 
     /**
@@ -3738,7 +3738,8 @@
     @Deprecated
     public void setAdditionalInputMethodSubtypes(@NonNull String imiId,
             @NonNull InputMethodSubtype[] subtypes) {
-        mServiceInvoker.setAdditionalInputMethodSubtypes(imiId, subtypes, UserHandle.myUserId());
+        IInputMethodManagerGlobalInvoker.setAdditionalInputMethodSubtypes(imiId, subtypes,
+                UserHandle.myUserId());
     }
 
     /**
@@ -3787,8 +3788,8 @@
      */
     public void setExplicitlyEnabledInputMethodSubtypes(@NonNull String imiId,
             @NonNull int[] subtypeHashCodes) {
-        mServiceInvoker.setExplicitlyEnabledInputMethodSubtypes(imiId, subtypeHashCodes,
-                UserHandle.myUserId());
+        IInputMethodManagerGlobalInvoker.setExplicitlyEnabledInputMethodSubtypes(imiId,
+                subtypeHashCodes, UserHandle.myUserId());
     }
 
     /**
@@ -3798,7 +3799,7 @@
      */
     @Nullable
     public InputMethodSubtype getLastInputMethodSubtype() {
-        return mServiceInvoker.getLastInputMethodSubtype(UserHandle.myUserId());
+        return IInputMethodManagerGlobalInvoker.getLastInputMethodSubtype(UserHandle.myUserId());
     }
 
     /**