1 /*
2  * Copyright (C) 2007-2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package android.view.inputmethod;
18 
19 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
20 import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
21 
22 import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION;
23 import static com.android.internal.inputmethod.StartInputReason.WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION;
24 
25 import android.annotation.DrawableRes;
26 import android.annotation.NonNull;
27 import android.annotation.Nullable;
28 import android.annotation.RequiresFeature;
29 import android.annotation.RequiresPermission;
30 import android.annotation.SystemService;
31 import android.annotation.TestApi;
32 import android.annotation.UserIdInt;
33 import android.app.ActivityThread;
34 import android.compat.annotation.UnsupportedAppUsage;
35 import android.content.ComponentName;
36 import android.content.ContentResolver;
37 import android.content.Context;
38 import android.content.pm.PackageManager;
39 import android.graphics.Matrix;
40 import android.graphics.Rect;
41 import android.inputmethodservice.InputMethodService;
42 import android.os.Binder;
43 import android.os.Build;
44 import android.os.Bundle;
45 import android.os.Handler;
46 import android.os.IBinder;
47 import android.os.Looper;
48 import android.os.Message;
49 import android.os.Process;
50 import android.os.RemoteException;
51 import android.os.ResultReceiver;
52 import android.os.ServiceManager;
53 import android.os.ServiceManager.ServiceNotFoundException;
54 import android.os.Trace;
55 import android.os.UserHandle;
56 import android.provider.Settings;
57 import android.text.style.SuggestionSpan;
58 import android.util.Log;
59 import android.util.Pools.Pool;
60 import android.util.Pools.SimplePool;
61 import android.util.PrintWriterPrinter;
62 import android.util.Printer;
63 import android.util.SparseArray;
64 import android.view.Display;
65 import android.view.ImeFocusController;
66 import android.view.ImeInsetsSourceConsumer;
67 import android.view.InputChannel;
68 import android.view.InputEvent;
69 import android.view.InputEventSender;
70 import android.view.KeyEvent;
71 import android.view.View;
72 import android.view.ViewRootImpl;
73 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
74 import android.view.autofill.AutofillManager;
75 
76 import com.android.internal.annotations.GuardedBy;
77 import com.android.internal.inputmethod.InputMethodDebug;
78 import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
79 import com.android.internal.inputmethod.StartInputFlags;
80 import com.android.internal.inputmethod.StartInputReason;
81 import com.android.internal.inputmethod.UnbindReason;
82 import com.android.internal.os.SomeArgs;
83 import com.android.internal.view.IInputConnectionWrapper;
84 import com.android.internal.view.IInputContext;
85 import com.android.internal.view.IInputMethodClient;
86 import com.android.internal.view.IInputMethodManager;
87 import com.android.internal.view.IInputMethodSession;
88 import com.android.internal.view.InputBindResult;
89 
90 import java.io.FileDescriptor;
91 import java.io.PrintWriter;
92 import java.lang.ref.WeakReference;
93 import java.lang.reflect.Proxy;
94 import java.util.Arrays;
95 import java.util.Collections;
96 import java.util.Comparator;
97 import java.util.List;
98 import java.util.Map;
99 import java.util.Objects;
100 import java.util.concurrent.CountDownLatch;
101 import java.util.concurrent.ThreadFactory;
102 import java.util.concurrent.TimeUnit;
103 
104 /**
105  * Central system API to the overall input method framework (IMF) architecture,
106  * which arbitrates interaction between applications and the current input method.
107  *
108  * <p>Topics covered here:
109  * <ol>
110  * <li><a href="#ArchitectureOverview">Architecture Overview</a>
111  * <li><a href="#Applications">Applications</a>
112  * <li><a href="#InputMethods">Input Methods</a>
113  * <li><a href="#Security">Security</a>
114  * </ol>
115  *
116  * <a name="ArchitectureOverview"></a>
117  * <h3>Architecture Overview</h3>
118  *
119  * <p>There are three primary parties involved in the input method
120  * framework (IMF) architecture:</p>
121  *
122  * <ul>
123  * <li> The <strong>input method manager</strong> as expressed by this class
124  * is the central point of the system that manages interaction between all
125  * other parts.  It is expressed as the client-side API here which exists
126  * in each application context and communicates with a global system service
127  * that manages the interaction across all processes.
128  * <li> An <strong>input method (IME)</strong> implements a particular
129  * interaction model allowing the user to generate text.  The system binds
130  * to the current input method that is in use, causing it to be created and run,
131  * and tells it when to hide and show its UI.  Only one IME is running at a time.
132  * <li> Multiple <strong>client applications</strong> arbitrate with the input
133  * method manager for input focus and control over the state of the IME.  Only
134  * one such client is ever active (working with the IME) at a time.
135  * </ul>
136  *
137  *
138  * <a name="Applications"></a>
139  * <h3>Applications</h3>
140  *
141  * <p>In most cases, applications that are using the standard
142  * {@link android.widget.TextView} or its subclasses will have little they need
143  * to do to work well with soft input methods.  The main things you need to
144  * be aware of are:</p>
145  *
146  * <ul>
147  * <li> Properly set the {@link android.R.attr#inputType} in your editable
148  * text views, so that the input method will have enough context to help the
149  * user in entering text into them.
150  * <li> Deal well with losing screen space when the input method is
151  * displayed.  Ideally an application should handle its window being resized
152  * smaller, but it can rely on the system performing panning of the window
153  * if needed.  You should set the {@link android.R.attr#windowSoftInputMode}
154  * attribute on your activity or the corresponding values on windows you
155  * create to help the system determine whether to pan or resize (it will
156  * try to determine this automatically but may get it wrong).
157  * <li> You can also control the preferred soft input state (open, closed, etc)
158  * for your window using the same {@link android.R.attr#windowSoftInputMode}
159  * attribute.
160  * </ul>
161  *
162  * <p>More finer-grained control is available through the APIs here to directly
163  * interact with the IMF and its IME -- either showing or hiding the input
164  * area, letting the user pick an input method, etc.</p>
165  *
166  * <p>For the rare people amongst us writing their own text editors, you
167  * will need to implement {@link android.view.View#onCreateInputConnection}
168  * to return a new instance of your own {@link InputConnection} interface
169  * allowing the IME to interact with your editor.</p>
170  *
171  *
172  * <a name="InputMethods"></a>
173  * <h3>Input Methods</h3>
174  *
175  * <p>An input method (IME) is implemented
176  * as a {@link android.app.Service}, typically deriving from
177  * {@link android.inputmethodservice.InputMethodService}.  It must provide
178  * the core {@link InputMethod} interface, though this is normally handled by
179  * {@link android.inputmethodservice.InputMethodService} and implementors will
180  * only need to deal with the higher-level API there.</p>
181  *
182  * See the {@link android.inputmethodservice.InputMethodService} class for
183  * more information on implementing IMEs.
184  *
185  *
186  * <a name="Security"></a>
187  * <h3>Security</h3>
188  *
189  * <p>There are a lot of security issues associated with input methods,
190  * since they essentially have freedom to completely drive the UI and monitor
191  * everything the user enters.  The Android input method framework also allows
192  * arbitrary third party IMEs, so care must be taken to restrict their
193  * selection and interactions.</p>
194  *
195  * <p>Here are some key points about the security architecture behind the
196  * IMF:</p>
197  *
198  * <ul>
199  * <li> <p>Only the system is allowed to directly access an IME's
200  * {@link InputMethod} interface, via the
201  * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission.  This is
202  * enforced in the system by not binding to an input method service that does
203  * not require this permission, so the system can guarantee no other untrusted
204  * clients are accessing the current input method outside of its control.</p>
205  *
206  * <li> <p>There may be many client processes of the IMF, but only one may
207  * be active at a time.  The inactive clients can not interact with key
208  * parts of the IMF through the mechanisms described below.</p>
209  *
210  * <li> <p>Clients of an input method are only given access to its
211  * {@link InputMethodSession} interface.  One instance of this interface is
212  * created for each client, and only calls from the session associated with
213  * the active client will be processed by the current IME.  This is enforced
214  * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
215  * IMEs, but must be explicitly handled by an IME that is customizing the
216  * raw {@link InputMethodSession} implementation.</p>
217  *
218  * <li> <p>Only the active client's {@link InputConnection} will accept
219  * operations.  The IMF tells each client process whether it is active, and
220  * the framework enforces that in inactive processes calls on to the current
221  * InputConnection will be ignored.  This ensures that the current IME can
222  * only deliver events and text edits to the UI that the user sees as
223  * being in focus.</p>
224  *
225  * <li> <p>An IME can never interact with an {@link InputConnection} while
226  * the screen is off.  This is enforced by making all clients inactive while
227  * the screen is off, and prevents bad IMEs from driving the UI when the user
228  * can not be aware of its behavior.</p>
229  *
230  * <li> <p>A client application can ask that the system let the user pick a
231  * new IME, but can not programmatically switch to one itself.  This avoids
232  * malicious applications from switching the user to their own IME, which
233  * remains running when the user navigates away to another application.  An
234  * IME, on the other hand, <em>is</em> allowed to programmatically switch
235  * the system to another IME, since it already has full control of user
236  * input.</p>
237  *
238  * <li> <p>The user must explicitly enable a new IME in settings before
239  * they can switch to it, to confirm with the system that they know about it
240  * and want to make it available for use.</p>
241  * </ul>
242  */
243 @SystemService(Context.INPUT_METHOD_SERVICE)
244 @RequiresFeature(PackageManager.FEATURE_INPUT_METHODS)
245 public final class InputMethodManager {
246     static final boolean DEBUG = false;
247     static final String TAG = "InputMethodManager";
248 
249     static final String PENDING_EVENT_COUNTER = "aq:imm";
250 
251     private static final int NOT_A_SUBTYPE_ID = -1;
252 
253     /**
254      * A constant that represents Voice IME.
255      *
256      * @see InputMethodSubtype#getMode()
257      */
258     private static final String SUBTYPE_MODE_VOICE = "voice";
259 
260     /**
261      * Ensures that {@link #sInstance} becomes non-{@code null} for application that have directly
262      * or indirectly relied on {@link #sInstance} via reflection or something like that.
263      *
264      * <p>Here are scenarios we know and there could be more scenarios we are not
265      * aware of right know.</p>
266      *
267      * <ul>
268      *     <li>Apps that directly access {@link #sInstance} via reflection, which is currently
269      *     allowed because of {@link UnsupportedAppUsage} annotation.  Currently
270      *     {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
271      *     {@link #sInstance} is not {@code null} when such an app is accessing it, but removing
272      *     that code from {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal
273      *     untested code paths in their apps, which probably happen in an early startup time of that
274      *     app.</li>
275      *     <li>Apps that directly access {@link #peekInstance()} via reflection, which is currently
276      *     allowed because of {@link UnsupportedAppUsage} annotation.  Currently
277      *     {@link android.view.WindowManagerGlobal#getWindowSession()} is likely to guarantee that
278      *     {@link #peekInstance()} returns non-{@code null} object when such an app is calling
279      *     {@link #peekInstance()}, but removing that code from
280      *     {@link android.view.WindowManagerGlobal#getWindowSession()} can reveal untested code
281      *     paths in their apps, which probably happen in an early startup time of that app. The good
282      *     news is that unlike {@link #sInstance}'s case we can at least work around this scenario
283      *     by changing the semantics of {@link #peekInstance()}, which is currently defined as
284      *     "retrieve the global {@link InputMethodManager} instance, if it exists" to something that
285      *     always returns non-{@code null} {@link InputMethodManager}.  However, introducing such an
286      *     workaround can also trigger different compatibility issues if {@link #peekInstance()} was
287      *     called before {@link android.view.WindowManagerGlobal#getWindowSession()} and it expected
288      *     {@link #peekInstance()} to return {@code null} as written in the JavaDoc.</li>
289      * </ul>
290      *
291      * <p>Since this is purely a compatibility hack, this method must be used only from
292      * {@link android.view.WindowManagerGlobal#getWindowSession()} and {@link #getInstance()}.</p>
293      *
294      * <p>TODO(Bug 116157766): Remove this method once we clean up {@link UnsupportedAppUsage}.</p>
295      * @hide
296      */
ensureDefaultInstanceForDefaultDisplayIfNecessary()297     public static void ensureDefaultInstanceForDefaultDisplayIfNecessary() {
298         forContextInternal(Display.DEFAULT_DISPLAY, Looper.getMainLooper());
299     }
300 
301     private static final Object sLock = new Object();
302 
303     /**
304      * @deprecated This cannot be compatible with multi-display. Please do not use this.
305      */
306     @Deprecated
307     @GuardedBy("sLock")
308     @UnsupportedAppUsage
309     static InputMethodManager sInstance;
310 
311     /**
312      * Global map between display to {@link InputMethodManager}.
313      *
314      * <p>Currently this map works like a so-called leaky singleton.  Once an instance is registered
315      * for the associated display ID, that instance will never be garbage collected.</p>
316      *
317      * <p>TODO(Bug 116699479): Implement instance clean up mechanism.</p>
318      */
319     @GuardedBy("sLock")
320     private static final SparseArray<InputMethodManager> sInstanceMap = new SparseArray<>();
321 
322     /**
323      * Timeout in milliseconds for delivering a key to an IME.
324      */
325     static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
326 
327     /** @hide */
328     public static final int DISPATCH_IN_PROGRESS = -1;
329 
330     /** @hide */
331     public static final int DISPATCH_NOT_HANDLED = 0;
332 
333     /** @hide */
334     public static final int DISPATCH_HANDLED = 1;
335 
336     /** @hide */
337     public static final int SHOW_IM_PICKER_MODE_AUTO = 0;
338     /** @hide */
339     public static final int SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES = 1;
340     /** @hide */
341     public static final int SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES = 2;
342 
343     @UnsupportedAppUsage
344     final IInputMethodManager mService;
345     final Looper mMainLooper;
346 
347     // For scheduling work on the main thread.  This also serves as our
348     // global lock.
349     // Remark on @UnsupportedAppUsage: there were context leaks on old versions
350     // of android (b/37043700), so developers used this field to perform manual clean up.
351     // Leaks were fixed, hacks were backported to AppCompatActivity,
352     // so an access to the field is closed.
353     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
354     final H mH;
355 
356     // Our generic input connection if the current target does not have its own.
357     final IInputContext mIInputContext;
358 
359     private final int mDisplayId;
360 
361     /**
362      * True if this input method client is active, initially false.
363      */
364     boolean mActive = false;
365 
366     /**
367      * {@code true} if next {@link ImeFocusController#onPostWindowFocus} needs to
368      * restart input.
369      */
370     private boolean mRestartOnNextWindowFocus = true;
371 
372     /**
373      * As reported by IME through InputConnection.
374      */
375     boolean mFullscreenMode;
376 
377     // -----------------------------------------------------------
378 
379     /**
380      * This is the root view of the overall window that currently has input
381      * method focus.
382      */
383     @GuardedBy("mH")
384     ViewRootImpl mCurRootView;
385     /**
386      * This is set when we are in the process of connecting, to determine
387      * when we have actually finished.
388      */
389     boolean mServedConnecting;
390     /**
391      * This is non-null when we have connected the served view; it holds
392      * the attributes that were last retrieved from the served view and given
393      * to the input connection.
394      */
395     EditorInfo mCurrentTextBoxAttribute;
396     /**
397      * The InputConnection that was last retrieved from the served view.
398      */
399     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
400     ControlledInputConnectionWrapper mServedInputConnectionWrapper;
401     /**
402      * The completions that were last provided by the served view.
403      */
404     CompletionInfo[] mCompletions;
405 
406     // Cursor position on the screen.
407     @UnsupportedAppUsage
408     Rect mTmpCursorRect = new Rect();
409     @UnsupportedAppUsage
410     Rect mCursorRect = new Rect();
411     int mCursorSelStart;
412     int mCursorSelEnd;
413     int mCursorCandStart;
414     int mCursorCandEnd;
415 
416     /**
417      * The instance that has previously been sent to the input method.
418      */
419     private CursorAnchorInfo mCursorAnchorInfo = null;
420 
421     /**
422      * A special {@link Matrix} that can be provided by the system when this instance is running
423      * inside a virtual display that is managed by {@link android.app.ActivityView}.
424      *
425      * <p>If this is non-{@code null}, {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}
426      * should be adjusted with this {@link Matrix}.</p>
427      *
428      * <p>{@code null} when not used.</p>
429      */
430     private Matrix mActivityViewToScreenMatrix = null;
431 
432     // -----------------------------------------------------------
433 
434     /**
435      * Sequence number of this binding, as returned by the server.
436      */
437     int mBindSequence = -1;
438     /**
439      * ID of the method we are bound to.
440      */
441     @UnsupportedAppUsage
442     String mCurId;
443     /**
444      * The actual instance of the method to make calls on it.
445      */
446     @UnsupportedAppUsage
447     IInputMethodSession mCurMethod;
448     InputChannel mCurChannel;
449     ImeInputEventSender mCurSender;
450 
451     private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
452 
453     /**
454      * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
455      */
456     private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
457 
458     /**
459      * When {@link ViewRootImpl#sNewInsetsMode} is set to
460      * >= {@link ViewRootImpl#NEW_INSETS_MODE_IME}, {@link ImeInsetsSourceConsumer} applies the
461      * IME visibility and listens for other state changes.
462      */
463     private ImeInsetsSourceConsumer mImeInsetsConsumer;
464 
465     final Pool<PendingEvent> mPendingEventPool = new SimplePool<>(20);
466     final SparseArray<PendingEvent> mPendingEvents = new SparseArray<>(20);
467 
468     final DelegateImpl mDelegate = new DelegateImpl();
469 
470     // -----------------------------------------------------------
471 
472     static final int MSG_DUMP = 1;
473     static final int MSG_BIND = 2;
474     static final int MSG_UNBIND = 3;
475     static final int MSG_SET_ACTIVE = 4;
476     static final int MSG_SEND_INPUT_EVENT = 5;
477     static final int MSG_TIMEOUT_INPUT_EVENT = 6;
478     static final int MSG_FLUSH_INPUT_EVENT = 7;
479     static final int MSG_REPORT_FULLSCREEN_MODE = 10;
480     static final int MSG_REPORT_PRE_RENDERED = 15;
481     static final int MSG_APPLY_IME_VISIBILITY = 20;
482     static final int MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX = 30;
483 
isAutofillUIShowing(View servedView)484     private static boolean isAutofillUIShowing(View servedView) {
485         AutofillManager afm = servedView.getContext().getSystemService(AutofillManager.class);
486         return afm != null && afm.isAutofillUiShowing();
487     }
488 
489     /**
490      * Returns fallback {@link InputMethodManager} if the called one is not likely to be compatible
491      * with the given {@code view}.
492      *
493      * @param view {@link View} to be checked.
494      * @return {@code null} when it is unnecessary (or impossible) to use fallback
495      *         {@link InputMethodManager} to which IME API calls need to be re-dispatched.
496      *          Non-{@code null} {@link InputMethodManager} if this method believes it'd be safer to
497      *          re-dispatch IME APIs calls on it.
498      */
499     @Nullable
getFallbackInputMethodManagerIfNecessary(@ullable View view)500     private InputMethodManager getFallbackInputMethodManagerIfNecessary(@Nullable View view) {
501         if (view == null) {
502             return null;
503         }
504         // As evidenced in Bug 118341760, view.getViewRootImpl().getDisplayId() is supposed to be
505         // more reliable to determine with which display the given view is interacting than
506         // view.getContext().getDisplayId() / view.getContext().getSystemService(), which can be
507         // easily messed up by app developers (or library authors) by creating inconsistent
508         // ContextWrapper objects that re-dispatch those methods to other Context such as
509         // ApplicationContext.
510         final ViewRootImpl viewRootImpl = view.getViewRootImpl();
511         if (viewRootImpl == null) {
512             return null;
513         }
514         final int viewRootDisplayId = viewRootImpl.getDisplayId();
515         if (viewRootDisplayId == mDisplayId) {
516             // Expected case.  Good to go.
517             return null;
518         }
519         final InputMethodManager fallbackImm =
520                 viewRootImpl.mContext.getSystemService(InputMethodManager.class);
521         if (fallbackImm == null) {
522             Log.v(TAG, "b/117267690: Failed to get non-null fallback IMM. view=" + view);
523             return null;
524         }
525         if (fallbackImm.mDisplayId != viewRootDisplayId) {
526             Log.v(TAG, "b/117267690: Failed to get fallback IMM with expected displayId="
527                     + viewRootDisplayId + " actual IMM#displayId=" + fallbackImm.mDisplayId
528                     + " view=" + view);
529             return null;
530         }
531         Log.v(TAG, "b/117267690: Display ID mismatch found."
532                 + " ViewRootImpl displayId=" + viewRootDisplayId
533                 + " InputMethodManager displayId=" + mDisplayId
534                 + ". Use the right InputMethodManager instance to avoid performance overhead.",
535                 new Throwable());
536         return fallbackImm;
537     }
538 
canStartInput(View servedView)539     private static boolean canStartInput(View servedView) {
540         // We can start input ether the servedView has window focus
541         // or the activity is showing autofill ui.
542         return servedView.hasWindowFocus() || isAutofillUIShowing(servedView);
543     }
544 
545     /**
546      * Reports whether the IME is currently perceptible or not, according to the leash applied by
547      * {@link android.view.WindowInsetsController}.
548      * @hide
549      */
reportPerceptible(IBinder windowToken, boolean perceptible)550     public void reportPerceptible(IBinder windowToken, boolean perceptible) {
551         try {
552             mService.reportPerceptible(windowToken, perceptible);
553         } catch (RemoteException e) {
554             throw e.rethrowFromSystemServer();
555         }
556     }
557 
558     private final class DelegateImpl implements
559             ImeFocusController.InputMethodManagerDelegate {
560         /**
561          * Used by {@link ImeFocusController} to start input connection.
562          */
563         @Override
startInput(@tartInputReason int startInputReason, View focusedView, @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int windowFlags)564         public boolean startInput(@StartInputReason int startInputReason, View focusedView,
565                 @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode,
566                 int windowFlags) {
567             final View servedView;
568             synchronized (mH) {
569                 mCurrentTextBoxAttribute = null;
570                 mCompletions = null;
571                 mServedConnecting = true;
572                 servedView = getServedViewLocked();
573             }
574             if (servedView != null && servedView.getHandler() != null) {
575                 // Make sure View checks should be on the UI thread.
576                 servedView.getHandler().post(() -> {
577                     if (!servedView.onCheckIsTextEditor()) {
578                         // servedView has changed and it's not editable.
579                         synchronized (mH) {
580                             maybeCallServedViewChangedLocked(null);
581                         }
582                     }
583                 });
584             }
585             return startInputInner(startInputReason,
586                     focusedView != null ? focusedView.getWindowToken() : null, startInputFlags,
587                     softInputMode, windowFlags);
588         }
589 
590         /**
591          * Used by {@link ImeFocusController} to finish input connection.
592          */
593         @Override
finishInput()594         public void finishInput() {
595             synchronized (mH) {
596                 finishInputLocked();
597             }
598         }
599 
600         /**
601          * Used by {@link ImeFocusController} to hide current input method editor.
602          */
603         @Override
closeCurrentIme()604         public void closeCurrentIme() {
605             closeCurrentInput();
606         }
607 
608         /**
609          * For {@link ImeFocusController} to start input asynchronously when focus gain.
610          */
611         @Override
startInputAsyncOnWindowFocusGain(View focusedView, @SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus)612         public void startInputAsyncOnWindowFocusGain(View focusedView,
613                 @SoftInputModeFlags int softInputMode, int windowFlags, boolean forceNewFocus) {
614             final int startInputFlags = getStartInputFlags(focusedView, 0);
615 
616             final ImeFocusController controller = getFocusController();
617             if (controller == null) {
618                 return;
619             }
620             if (controller.checkFocus(forceNewFocus, false)) {
621                 // We need to restart input on the current focus view.  This
622                 // should be done in conjunction with telling the system service
623                 // about the window gaining focus, to help make the transition
624                 // smooth.
625                 if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
626                         focusedView, startInputFlags, softInputMode, windowFlags)) {
627                     return;
628                 }
629             }
630 
631             synchronized (mH) {
632                 // For some reason we didn't do a startInput + windowFocusGain, so
633                 // we'll just do a window focus gain and call it a day.
634                 try {
635                     View servedView = controller.getServedView();
636                     boolean nextFocusHasConnection = servedView != null && servedView == focusedView
637                             && hasActiveConnection(focusedView);
638                     if (DEBUG) {
639                         Log.v(TAG, "Reporting focus gain, without startInput"
640                                 + ", nextFocusIsServedView=" + nextFocusHasConnection);
641                     }
642                     final int startInputReason =
643                             nextFocusHasConnection ? WINDOW_FOCUS_GAIN_REPORT_WITH_CONNECTION
644                                     : WINDOW_FOCUS_GAIN_REPORT_WITHOUT_CONNECTION;
645                     mService.startInputOrWindowGainedFocus(
646                             startInputReason, mClient,
647                             focusedView.getWindowToken(), startInputFlags, softInputMode,
648                             windowFlags,
649                             null,
650                             null,
651                             0 /* missingMethodFlags */,
652                             mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
653                 } catch (RemoteException e) {
654                     throw e.rethrowFromSystemServer();
655                 }
656             }
657         }
658 
659         /**
660          * Used by {@link ImeFocusController} to finish current composing text.
661          */
662         @Override
finishComposingText()663         public void finishComposingText() {
664             if (mServedInputConnectionWrapper != null) {
665                 mServedInputConnectionWrapper.finishComposingText();
666             }
667         }
668 
669         /**
670          * Used for {@link ImeFocusController} to set the current focused root view.
671          */
672         @Override
setCurrentRootView(ViewRootImpl rootView)673         public void setCurrentRootView(ViewRootImpl rootView) {
674             synchronized (mH) {
675                 mCurRootView = rootView;
676             }
677         }
678 
679         /**
680          * Used for {@link ImeFocusController} to return if the root view from the
681          * controller is this {@link InputMethodManager} currently focused.
682          * TODO: Address event-order problem when get current root view in multi-threads.
683          */
684         @Override
isCurrentRootView(ViewRootImpl rootView)685         public boolean isCurrentRootView(ViewRootImpl rootView) {
686             synchronized (mH) {
687                 return mCurRootView == rootView;
688             }
689         }
690 
691         /**
692          * For {@link ImeFocusController#checkFocus} if needed to force check new focus.
693          */
694         @Override
isRestartOnNextWindowFocus(boolean reset)695         public boolean isRestartOnNextWindowFocus(boolean reset) {
696             final boolean result = mRestartOnNextWindowFocus;
697             if (reset) {
698                 mRestartOnNextWindowFocus = false;
699             }
700             return result;
701         }
702 
703         /**
704          * Checks whether the active input connection (if any) is for the given view.
705          *
706          * TODO(b/160968797): Remove this method and move mServedInputConnectionWrapper to
707          *  ImeFocusController.
708          *
709          * Note that this method is only intended for restarting input after focus gain
710          * (e.g. b/160391516), DO NOT leverage this method to do another check.
711          */
712         @Override
hasActiveConnection(View view)713         public boolean hasActiveConnection(View view) {
714             synchronized (mH) {
715                 if (!hasServedByInputMethodLocked(view)) {
716                     return false;
717                 }
718 
719                 return mServedInputConnectionWrapper != null
720                         && mServedInputConnectionWrapper.isActive()
721                         && mServedInputConnectionWrapper.mServedView.get() == view;
722             }
723         }
724     }
725 
726     /** @hide */
getDelegate()727     public DelegateImpl getDelegate() {
728         return mDelegate;
729     }
730 
getServedViewLocked()731     private View getServedViewLocked() {
732         return mCurRootView != null ? mCurRootView.getImeFocusController().getServedView() : null;
733     }
734 
getNextServedViewLocked()735     private View getNextServedViewLocked() {
736         return mCurRootView != null ? mCurRootView.getImeFocusController().getNextServedView()
737                 : null;
738     }
739 
setServedViewLocked(View view)740     private void setServedViewLocked(View view) {
741         if (mCurRootView != null) {
742             mCurRootView.getImeFocusController().setServedView(view);
743         }
744     }
745 
setNextServedViewLocked(View view)746     private void setNextServedViewLocked(View view) {
747         if (mCurRootView != null) {
748             mCurRootView.getImeFocusController().setNextServedView(view);
749         }
750     }
751 
getFocusController()752     private ImeFocusController getFocusController() {
753         synchronized (mH) {
754             if (mCurRootView != null) {
755                 return mCurRootView.getImeFocusController();
756             }
757             return null;
758         }
759     }
760 
761     /**
762      * Returns {@code true} when the given view has been served by Input Method.
763      */
hasServedByInputMethodLocked(View view)764     private boolean hasServedByInputMethodLocked(View view) {
765         final View servedView = getServedViewLocked();
766         return (servedView == view
767                 || (servedView != null && servedView.checkInputConnectionProxy(view)));
768     }
769 
770     class H extends Handler {
H(Looper looper)771         H(Looper looper) {
772             super(looper, null, true);
773         }
774 
775         @Override
handleMessage(Message msg)776         public void handleMessage(Message msg) {
777             switch (msg.what) {
778                 case MSG_DUMP: {
779                     SomeArgs args = (SomeArgs)msg.obj;
780                     try {
781                         doDump((FileDescriptor)args.arg1,
782                                 (PrintWriter)args.arg2, (String[])args.arg3);
783                     } catch (RuntimeException e) {
784                         ((PrintWriter)args.arg2).println("Exception: " + e);
785                     }
786                     synchronized (args.arg4) {
787                         ((CountDownLatch)args.arg4).countDown();
788                     }
789                     args.recycle();
790                     return;
791                 }
792                 case MSG_BIND: {
793                     final InputBindResult res = (InputBindResult)msg.obj;
794                     if (DEBUG) {
795                         Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
796                     }
797                     synchronized (mH) {
798                         if (mBindSequence < 0 || mBindSequence != res.sequence) {
799                             Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
800                                     + ", given seq=" + res.sequence);
801                             if (res.channel != null && res.channel != mCurChannel) {
802                                 res.channel.dispose();
803                             }
804                             return;
805                         }
806 
807                         mRequestUpdateCursorAnchorInfoMonitorMode =
808                                 REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
809 
810                         setInputChannelLocked(res.channel);
811                         mCurMethod = res.method;
812                         mCurId = res.id;
813                         mBindSequence = res.sequence;
814                         mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
815                     }
816                     startInputInner(StartInputReason.BOUND_TO_IMMS, null, 0, 0, 0);
817                     return;
818                 }
819                 case MSG_UNBIND: {
820                     final int sequence = msg.arg1;
821                     @UnbindReason
822                     final int reason = msg.arg2;
823                     if (DEBUG) {
824                         Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence +
825                                 " reason=" + InputMethodDebug.unbindReasonToString(reason));
826                     }
827                     final boolean startInput;
828                     synchronized (mH) {
829                         if (mBindSequence != sequence) {
830                             return;
831                         }
832                         clearBindingLocked();
833                         // If we were actively using the last input method, then
834                         // we would like to re-connect to the next input method.
835                         final View servedView = getServedViewLocked();
836                         if (servedView != null && servedView.isFocused()) {
837                             mServedConnecting = true;
838                         }
839                         startInput = mActive;
840                     }
841                     if (startInput) {
842                         startInputInner(
843                                 StartInputReason.UNBOUND_FROM_IMMS, null, 0, 0, 0);
844                     }
845                     return;
846                 }
847                 case MSG_SET_ACTIVE: {
848                     final boolean active = msg.arg1 != 0;
849                     final boolean fullscreen = msg.arg2 != 0;
850                     if (DEBUG) {
851                         Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
852                     }
853                     synchronized (mH) {
854                         mActive = active;
855                         mFullscreenMode = fullscreen;
856                         if (!active) {
857                             // Some other client has starting using the IME, so note
858                             // that this happened and make sure our own editor's
859                             // state is reset.
860                             mRestartOnNextWindowFocus = true;
861                             try {
862                                 // Note that finishComposingText() is allowed to run
863                                 // even when we are not active.
864                                 mIInputContext.finishComposingText();
865                             } catch (RemoteException e) {
866                             }
867                         }
868                         // Check focus again in case that "onWindowFocus" is called before
869                         // handling this message.
870                         final View servedView = getServedViewLocked();
871                         if (servedView != null && canStartInput(servedView)) {
872                             if (mCurRootView != null && mCurRootView.getImeFocusController()
873                                     .checkFocus(mRestartOnNextWindowFocus, false)) {
874                                 final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
875                                         : StartInputReason.DEACTIVATED_BY_IMMS;
876                                 mDelegate.startInput(reason, null, 0, 0, 0);
877                             }
878                         }
879                     }
880                     return;
881                 }
882                 case MSG_SEND_INPUT_EVENT: {
883                     sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
884                     return;
885                 }
886                 case MSG_TIMEOUT_INPUT_EVENT: {
887                     finishedInputEvent(msg.arg1, false, true);
888                     return;
889                 }
890                 case MSG_FLUSH_INPUT_EVENT: {
891                     finishedInputEvent(msg.arg1, false, false);
892                     return;
893                 }
894                 case MSG_REPORT_FULLSCREEN_MODE: {
895                     final boolean fullscreen = msg.arg1 != 0;
896                     InputConnection ic = null;
897                     synchronized (mH) {
898                         mFullscreenMode = fullscreen;
899                         if (mServedInputConnectionWrapper != null) {
900                             ic = mServedInputConnectionWrapper.getInputConnection();
901                         }
902                     }
903                     if (ic != null) {
904                         ic.reportFullscreenMode(fullscreen);
905                     }
906                     return;
907                 }
908                 case MSG_REPORT_PRE_RENDERED: {
909                     synchronized (mH) {
910                         if (mImeInsetsConsumer != null) {
911                             mImeInsetsConsumer.onPreRendered((EditorInfo) msg.obj);
912                         }
913                     }
914                     return;
915 
916                 }
917                 case MSG_APPLY_IME_VISIBILITY: {
918                     synchronized (mH) {
919                         if (mImeInsetsConsumer != null) {
920                             mImeInsetsConsumer.applyImeVisibility(msg.arg1 != 0);
921                         }
922                     }
923                     return;
924                 }
925                 case MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX: {
926                     final float[] matrixValues = (float[]) msg.obj;
927                     final int bindSequence = msg.arg1;
928                     synchronized (mH) {
929                         if (mBindSequence != bindSequence) {
930                             return;
931                         }
932                         if (matrixValues == null || mActivityViewToScreenMatrix == null) {
933                             // Either InputBoundResult#mActivityViewToScreenMatrixValues is null
934                             // OR this app is unbound from the parent ActivityView. In this case,
935                             // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
936                             mActivityViewToScreenMatrix = null;
937                             return;
938                         }
939 
940                         final float[] currentValues = new float[9];
941                         mActivityViewToScreenMatrix.getValues(currentValues);
942                         if (Arrays.equals(currentValues, matrixValues)) {
943                             return;
944                         }
945                         mActivityViewToScreenMatrix.setValues(matrixValues);
946 
947                         if (mCursorAnchorInfo == null || mCurMethod == null
948                                 || mServedInputConnectionWrapper == null) {
949                             return;
950                         }
951                         final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode
952                                 & InputConnection.CURSOR_UPDATE_MONITOR) != 0;
953                         if (!isMonitoring) {
954                             return;
955                         }
956                         // Since the host ActivityView is moved, we need to issue
957                         // IMS#updateCursorAnchorInfo() again.
958                         try {
959                             mCurMethod.updateCursorAnchorInfo(
960                                     CursorAnchorInfo.createForAdditionalParentMatrix(
961                                             mCursorAnchorInfo, mActivityViewToScreenMatrix));
962                         } catch (RemoteException e) {
963                             Log.w(TAG, "IME died: " + mCurId, e);
964                         }
965                     }
966                     return;
967                 }
968             }
969         }
970     }
971 
972     private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
973         private final InputMethodManager mParentInputMethodManager;
974         private final WeakReference<View> mServedView;
975 
ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn, InputMethodManager inputMethodManager, View servedView)976         ControlledInputConnectionWrapper(Looper mainLooper, InputConnection conn,
977                 InputMethodManager inputMethodManager, View servedView) {
978             super(mainLooper, conn);
979             mParentInputMethodManager = inputMethodManager;
980             mServedView = new WeakReference<>(servedView);
981         }
982 
983         @Override
isActive()984         public boolean isActive() {
985             return mParentInputMethodManager.mActive && !isFinished();
986         }
987 
deactivate()988         void deactivate() {
989             if (isFinished()) {
990                 // This is a small performance optimization.  Still only the 1st call of
991                 // reportFinish() will take effect.
992                 return;
993             }
994             closeConnection();
995         }
996 
997         @Override
toString()998         public String toString() {
999             return "ControlledInputConnectionWrapper{"
1000                     + "connection=" + getInputConnection()
1001                     + " finished=" + isFinished()
1002                     + " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
1003                     + " mServedView=" + mServedView.get()
1004                     + "}";
1005         }
1006     }
1007 
1008     private static class ImeThreadFactory implements ThreadFactory {
1009         private final String mThreadName;
1010 
ImeThreadFactory(String name)1011         ImeThreadFactory(String name) {
1012             mThreadName = name;
1013         }
1014 
1015         @Override
newThread(Runnable r)1016         public Thread newThread(Runnable r) {
1017             return new Thread(r, mThreadName);
1018         }
1019     }
1020 
1021     final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
1022         @Override
1023         protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
1024             // No need to check for dump permission, since we only give this
1025             // interface to the system.
1026             CountDownLatch latch = new CountDownLatch(1);
1027             SomeArgs sargs = SomeArgs.obtain();
1028             sargs.arg1 = fd;
1029             sargs.arg2 = fout;
1030             sargs.arg3 = args;
1031             sargs.arg4 = latch;
1032             mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
1033             try {
1034                 if (!latch.await(5, TimeUnit.SECONDS)) {
1035                     fout.println("Timeout waiting for dump");
1036                 }
1037             } catch (InterruptedException e) {
1038                 fout.println("Interrupted waiting for dump");
1039             }
1040         }
1041 
1042         @Override
1043         public void onBindMethod(InputBindResult res) {
1044             mH.obtainMessage(MSG_BIND, res).sendToTarget();
1045         }
1046 
1047         @Override
1048         public void onUnbindMethod(int sequence, @UnbindReason int unbindReason) {
1049             mH.obtainMessage(MSG_UNBIND, sequence, unbindReason).sendToTarget();
1050         }
1051 
1052         @Override
1053         public void setActive(boolean active, boolean fullscreen) {
1054             mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, fullscreen ? 1 : 0).sendToTarget();
1055         }
1056 
1057         @Override
1058         public void scheduleStartInputIfNecessary(boolean fullscreen) {
1059             // TODO(b/149859205): See if we can optimize this by having a fused dedicated operation.
1060             mH.obtainMessage(MSG_SET_ACTIVE, 0 /* active */, fullscreen ? 1 : 0).sendToTarget();
1061             mH.obtainMessage(MSG_SET_ACTIVE, 1 /* active */, fullscreen ? 1 : 0).sendToTarget();
1062         }
1063 
1064         @Override
1065         public void reportFullscreenMode(boolean fullscreen) {
1066             mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
1067                     .sendToTarget();
1068         }
1069 
1070         @Override
1071         public void reportPreRendered(EditorInfo info) {
1072             mH.obtainMessage(MSG_REPORT_PRE_RENDERED, 0, 0, info)
1073                     .sendToTarget();
1074         }
1075 
1076         @Override
1077         public void applyImeVisibility(boolean setVisible) {
1078             mH.obtainMessage(MSG_APPLY_IME_VISIBILITY, setVisible ? 1 : 0, 0)
1079                     .sendToTarget();
1080         }
1081 
1082         @Override
1083         public void updateActivityViewToScreenMatrix(int bindSequence, float[] matrixValues) {
1084             mH.obtainMessage(MSG_UPDATE_ACTIVITY_VIEW_TO_SCREEN_MATRIX, bindSequence, 0,
1085                     matrixValues).sendToTarget();
1086         }
1087     };
1088 
1089     final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
1090 
1091     /**
1092      * For layoutlib to clean up static objects inside {@link InputMethodManager}.
1093      */
tearDownEditMode()1094     static void tearDownEditMode() {
1095         if (!isInEditMode()) {
1096             throw new UnsupportedOperationException(
1097                     "This method must be called only from layoutlib");
1098         }
1099         synchronized (sLock) {
1100             sInstance = null;
1101         }
1102     }
1103 
1104     /**
1105      * For layoutlib to override this method to return {@code true}.
1106      *
1107      * @return {@code true} if the process is running for developer tools
1108      * @see View#isInEditMode()
1109      */
isInEditMode()1110     private static boolean isInEditMode() {
1111         return false;
1112     }
1113 
1114     @NonNull
createInstance(int displayId, Looper looper)1115     private static InputMethodManager createInstance(int displayId, Looper looper) {
1116         return isInEditMode() ? createStubInstance(displayId, looper)
1117                 : createRealInstance(displayId, looper);
1118     }
1119 
1120     @NonNull
createRealInstance(int displayId, Looper looper)1121     private static InputMethodManager createRealInstance(int displayId, Looper looper) {
1122         final IInputMethodManager service;
1123         try {
1124             service = IInputMethodManager.Stub.asInterface(
1125                     ServiceManager.getServiceOrThrow(Context.INPUT_METHOD_SERVICE));
1126         } catch (ServiceNotFoundException e) {
1127             throw new IllegalStateException(e);
1128         }
1129         final InputMethodManager imm = new InputMethodManager(service, displayId, looper);
1130         // InputMethodManagerService#addClient() relies on Binder.getCalling{Pid, Uid}() to
1131         // associate PID/UID with each IME client. This means:
1132         //  A. if this method call will be handled as an IPC, there is no problem.
1133         //  B. if this method call will be handled as an in-proc method call, we need to
1134         //     ensure that Binder.getCalling{Pid, Uid}() return Process.my{Pid, Uid}()
1135         // Either ways we can always call Binder.{clear, restore}CallingIdentity() because
1136         // 1) doing so has no effect for A and 2) doing so is sufficient for B.
1137         final long identity = Binder.clearCallingIdentity();
1138         try {
1139             service.addClient(imm.mClient, imm.mIInputContext, displayId);
1140         } catch (RemoteException e) {
1141             e.rethrowFromSystemServer();
1142         } finally {
1143             Binder.restoreCallingIdentity(identity);
1144         }
1145         return imm;
1146     }
1147 
1148     @NonNull
createStubInstance(int displayId, Looper looper)1149     private static InputMethodManager createStubInstance(int displayId, Looper looper) {
1150         // If InputMethodManager is running for layoutlib, stub out IPCs into IMMS.
1151         final Class<IInputMethodManager> c = IInputMethodManager.class;
1152         final IInputMethodManager stubInterface =
1153                 (IInputMethodManager) Proxy.newProxyInstance(c.getClassLoader(),
1154                         new Class[]{c}, (proxy, method, args) -> {
1155                             final Class<?> returnType = method.getReturnType();
1156                             if (returnType == boolean.class) {
1157                                 return false;
1158                             } else if (returnType == int.class) {
1159                                 return 0;
1160                             } else if (returnType == long.class) {
1161                                 return 0L;
1162                             } else if (returnType == short.class) {
1163                                 return 0;
1164                             } else if (returnType == char.class) {
1165                                 return 0;
1166                             } else if (returnType == byte.class) {
1167                                 return 0;
1168                             } else if (returnType == float.class) {
1169                                 return 0f;
1170                             } else if (returnType == double.class) {
1171                                 return 0.0;
1172                             } else {
1173                                 return null;
1174                             }
1175                         });
1176         return new InputMethodManager(stubInterface, displayId, looper);
1177     }
1178 
InputMethodManager(IInputMethodManager service, int displayId, Looper looper)1179     private InputMethodManager(IInputMethodManager service, int displayId, Looper looper) {
1180         mService = service;
1181         mMainLooper = looper;
1182         mH = new H(looper);
1183         mDisplayId = displayId;
1184         mIInputContext = new ControlledInputConnectionWrapper(looper, mDummyInputConnection, this,
1185                 null);
1186     }
1187 
1188     /**
1189      * Retrieve an instance for the given {@link Context}, creating it if it doesn't already exist.
1190      *
1191      * @param context {@link Context} for which IME APIs need to work
1192      * @return {@link InputMethodManager} instance
1193      * @hide
1194      */
1195     @NonNull
forContext(Context context)1196     public static InputMethodManager forContext(Context context) {
1197         final int displayId = context.getDisplayId();
1198         // For better backward compatibility, we always use Looper.getMainLooper() for the default
1199         // display case.
1200         final Looper looper = displayId == Display.DEFAULT_DISPLAY
1201                 ? Looper.getMainLooper() : context.getMainLooper();
1202         return forContextInternal(displayId, looper);
1203     }
1204 
1205     @NonNull
forContextInternal(int displayId, Looper looper)1206     private static InputMethodManager forContextInternal(int displayId, Looper looper) {
1207         final boolean isDefaultDisplay = displayId == Display.DEFAULT_DISPLAY;
1208         synchronized (sLock) {
1209             InputMethodManager instance = sInstanceMap.get(displayId);
1210             if (instance != null) {
1211                 return instance;
1212             }
1213             instance = createInstance(displayId, looper);
1214             // For backward compatibility, store the instance also to sInstance for default display.
1215             if (sInstance == null && isDefaultDisplay) {
1216                 sInstance = instance;
1217             }
1218             sInstanceMap.put(displayId, instance);
1219             return instance;
1220         }
1221     }
1222 
1223     /**
1224      * Deprecated. Do not use.
1225      *
1226      * @return global {@link InputMethodManager} instance
1227      * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
1228      *             support multi-display scenario.
1229      * @hide
1230      */
1231     @Deprecated
1232     @UnsupportedAppUsage
getInstance()1233     public static InputMethodManager getInstance() {
1234         Log.w(TAG, "InputMethodManager.getInstance() is deprecated because it cannot be"
1235                         + " compatible with multi-display."
1236                         + " Use context.getSystemService(InputMethodManager.class) instead.",
1237                 new Throwable());
1238         ensureDefaultInstanceForDefaultDisplayIfNecessary();
1239         return peekInstance();
1240     }
1241 
1242     /**
1243      * Deprecated. Do not use.
1244      *
1245      * @return {@link #sInstance}
1246      * @deprecated Use {@link Context#getSystemService(Class)} instead. This method cannot fully
1247      *             support multi-display scenario.
1248      * @hide
1249      */
1250     @Deprecated
1251     @UnsupportedAppUsage
peekInstance()1252     public static InputMethodManager peekInstance() {
1253         Log.w(TAG, "InputMethodManager.peekInstance() is deprecated because it cannot be"
1254                         + " compatible with multi-display."
1255                         + " Use context.getSystemService(InputMethodManager.class) instead.",
1256                 new Throwable());
1257         synchronized (sLock) {
1258             return sInstance;
1259         }
1260     }
1261 
1262     /** @hide */
1263     @UnsupportedAppUsage
getClient()1264     public IInputMethodClient getClient() {
1265         return mClient;
1266     }
1267 
1268     /** @hide */
1269     @UnsupportedAppUsage
getInputContext()1270     public IInputContext getInputContext() {
1271         return mIInputContext;
1272     }
1273 
1274     /**
1275      * Returns the list of installed input methods.
1276      *
1277      * <p>On multi user environment, this API returns a result for the calling process user.</p>
1278      *
1279      * @return {@link List} of {@link InputMethodInfo}.
1280      */
getInputMethodList()1281     public List<InputMethodInfo> getInputMethodList() {
1282         try {
1283             // We intentionally do not use UserHandle.getCallingUserId() here because for system
1284             // services InputMethodManagerInternal.getInputMethodListAsUser() should be used
1285             // instead.
1286             return mService.getInputMethodList(UserHandle.myUserId());
1287         } catch (RemoteException e) {
1288             throw e.rethrowFromSystemServer();
1289         }
1290     }
1291 
1292     /**
1293      * Returns the list of installed input methods for the specified user.
1294      *
1295      * @param userId user ID to query
1296      * @return {@link List} of {@link InputMethodInfo}.
1297      * @hide
1298      */
1299     @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
getInputMethodListAsUser(@serIdInt int userId)1300     public List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId) {
1301         try {
1302             return mService.getInputMethodList(userId);
1303         } catch (RemoteException e) {
1304             throw e.rethrowFromSystemServer();
1305         }
1306     }
1307 
1308     /**
1309      * Returns the list of enabled input methods.
1310      *
1311      * <p>On multi user environment, this API returns a result for the calling process user.</p>
1312      *
1313      * @return {@link List} of {@link InputMethodInfo}.
1314      */
getEnabledInputMethodList()1315     public List<InputMethodInfo> getEnabledInputMethodList() {
1316         try {
1317             // We intentionally do not use UserHandle.getCallingUserId() here because for system
1318             // services InputMethodManagerInternal.getEnabledInputMethodListAsUser() should be used
1319             // instead.
1320             return mService.getEnabledInputMethodList(UserHandle.myUserId());
1321         } catch (RemoteException e) {
1322             throw e.rethrowFromSystemServer();
1323         }
1324     }
1325 
1326     /**
1327      * Returns the list of enabled input methods for the specified user.
1328      *
1329      * @param userId user ID to query
1330      * @return {@link List} of {@link InputMethodInfo}.
1331      * @hide
1332      */
1333     @RequiresPermission(INTERACT_ACROSS_USERS_FULL)
getEnabledInputMethodListAsUser(@serIdInt int userId)1334     public List<InputMethodInfo> getEnabledInputMethodListAsUser(@UserIdInt int userId) {
1335         try {
1336             return mService.getEnabledInputMethodList(userId);
1337         } catch (RemoteException e) {
1338             throw e.rethrowFromSystemServer();
1339         }
1340     }
1341 
1342     /**
1343      * Returns a list of enabled input method subtypes for the specified input method info.
1344      *
1345      * <p>On multi user environment, this API returns a result for the calling process user.</p>
1346      *
1347      * @param imi An input method info whose subtypes list will be returned.
1348      * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly
1349      * selected subtypes. If an input method info doesn't have enabled subtypes, the framework
1350      * will implicitly enable subtypes according to the current system language.
1351      */
getEnabledInputMethodSubtypeList(InputMethodInfo imi, boolean allowsImplicitlySelectedSubtypes)1352     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
1353             boolean allowsImplicitlySelectedSubtypes) {
1354         try {
1355             return mService.getEnabledInputMethodSubtypeList(
1356                     imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
1357         } catch (RemoteException e) {
1358             throw e.rethrowFromSystemServer();
1359         }
1360     }
1361 
1362     /**
1363      * @deprecated Use {@link InputMethodService#showStatusIcon(int)} instead. This method was
1364      * intended for IME developers who should be accessing APIs through the service. APIs in this
1365      * class are intended for app developers interacting with the IME.
1366      */
1367     @Deprecated
showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId)1368     public void showStatusIcon(IBinder imeToken, String packageName, @DrawableRes int iconId) {
1369         InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(packageName, iconId);
1370     }
1371 
1372     /**
1373      * @deprecated Use {@link InputMethodService#hideStatusIcon()} instead. This method was
1374      * intended for IME developers who should be accessing APIs through the service. APIs in
1375      * this class are intended for app developers interacting with the IME.
1376      */
1377     @Deprecated
hideStatusIcon(IBinder imeToken)1378     public void hideStatusIcon(IBinder imeToken) {
1379         InputMethodPrivilegedOperationsRegistry.get(imeToken).updateStatusIcon(null, 0);
1380     }
1381 
1382     /**
1383      * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1384      *
1385      * @param spans will be ignored.
1386      *
1387      * @deprecated Do not use.
1388      * @hide
1389      */
1390     @Deprecated
1391     @UnsupportedAppUsage
registerSuggestionSpansForNotification(SuggestionSpan[] spans)1392     public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
1393         Log.w(TAG, "registerSuggestionSpansForNotification() is deprecated.  Does nothing.");
1394     }
1395 
1396     /**
1397      * This hidden API is deprecated in {@link android.os.Build.VERSION_CODES#Q}. Does nothing.
1398      *
1399      * @deprecated Do not use.
1400      * @hide
1401      */
1402     @Deprecated
1403     @UnsupportedAppUsage
notifySuggestionPicked(SuggestionSpan span, String originalString, int index)1404     public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
1405         Log.w(TAG, "notifySuggestionPicked() is deprecated.  Does nothing.");
1406     }
1407 
1408     /**
1409      * Allows you to discover whether the attached input method is running
1410      * in fullscreen mode.  Return true if it is fullscreen, entirely covering
1411      * your UI, else returns false.
1412      */
isFullscreenMode()1413     public boolean isFullscreenMode() {
1414         synchronized (mH) {
1415             return mFullscreenMode;
1416         }
1417     }
1418 
1419     /**
1420      * Return true if the given view is the currently active view for the
1421      * input method.
1422      */
isActive(View view)1423     public boolean isActive(View view) {
1424         // Re-dispatch if there is a context mismatch.
1425         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1426         if (fallbackImm != null) {
1427             return fallbackImm.isActive(view);
1428         }
1429 
1430         checkFocus();
1431         synchronized (mH) {
1432             return hasServedByInputMethodLocked(view) && mCurrentTextBoxAttribute != null;
1433         }
1434     }
1435 
1436     /**
1437      * Return true if any view is currently active in the input method.
1438      */
isActive()1439     public boolean isActive() {
1440         checkFocus();
1441         synchronized (mH) {
1442             return getServedViewLocked() != null && mCurrentTextBoxAttribute != null;
1443         }
1444     }
1445 
1446     /**
1447      * Return true if the currently served view is accepting full text edits.
1448      * If false, it has no input connection, so can only handle raw key events.
1449      */
isAcceptingText()1450     public boolean isAcceptingText() {
1451         checkFocus();
1452         return mServedInputConnectionWrapper != null &&
1453                 mServedInputConnectionWrapper.getInputConnection() != null;
1454     }
1455 
1456     /**
1457      * Reset all of the state associated with being bound to an input method.
1458      */
clearBindingLocked()1459     void clearBindingLocked() {
1460         if (DEBUG) Log.v(TAG, "Clearing binding!");
1461         clearConnectionLocked();
1462         setInputChannelLocked(null);
1463         mBindSequence = -1;
1464         mCurId = null;
1465         mCurMethod = null;
1466     }
1467 
setInputChannelLocked(InputChannel channel)1468     void setInputChannelLocked(InputChannel channel) {
1469         if (mCurChannel != channel) {
1470             if (mCurSender != null) {
1471                 flushPendingEventsLocked();
1472                 mCurSender.dispose();
1473                 mCurSender = null;
1474             }
1475             if (mCurChannel != null) {
1476                 mCurChannel.dispose();
1477             }
1478             mCurChannel = channel;
1479         }
1480     }
1481 
1482     /**
1483      * Reset all of the state associated with a served view being connected
1484      * to an input method
1485      */
clearConnectionLocked()1486     void clearConnectionLocked() {
1487         mCurrentTextBoxAttribute = null;
1488         if (mServedInputConnectionWrapper != null) {
1489             mServedInputConnectionWrapper.deactivate();
1490             mServedInputConnectionWrapper = null;
1491         }
1492     }
1493 
1494     /**
1495      * Disconnect any existing input connection, clearing the served view.
1496      */
1497     @UnsupportedAppUsage
finishInputLocked()1498     void finishInputLocked() {
1499         mActivityViewToScreenMatrix = null;
1500         setNextServedViewLocked(null);
1501         if (getServedViewLocked() != null) {
1502             if (DEBUG) {
1503                 Log.v(TAG, "FINISH INPUT: mServedView="
1504                         + dumpViewInfo(getServedViewLocked()));
1505             }
1506             setServedViewLocked(null);
1507             mCompletions = null;
1508             mServedConnecting = false;
1509             clearConnectionLocked();
1510         }
1511     }
1512 
displayCompletions(View view, CompletionInfo[] completions)1513     public void displayCompletions(View view, CompletionInfo[] completions) {
1514         // Re-dispatch if there is a context mismatch.
1515         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1516         if (fallbackImm != null) {
1517             fallbackImm.displayCompletions(view, completions);
1518             return;
1519         }
1520 
1521         checkFocus();
1522         synchronized (mH) {
1523             if (!hasServedByInputMethodLocked(view)) {
1524                 return;
1525             }
1526 
1527             mCompletions = completions;
1528             if (mCurMethod != null) {
1529                 try {
1530                     mCurMethod.displayCompletions(mCompletions);
1531                 } catch (RemoteException e) {
1532                 }
1533             }
1534         }
1535     }
1536 
updateExtractedText(View view, int token, ExtractedText text)1537     public void updateExtractedText(View view, int token, ExtractedText text) {
1538         // Re-dispatch if there is a context mismatch.
1539         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1540         if (fallbackImm != null) {
1541             fallbackImm.updateExtractedText(view, token, text);
1542             return;
1543         }
1544 
1545         checkFocus();
1546         synchronized (mH) {
1547             if (!hasServedByInputMethodLocked(view)) {
1548                 return;
1549             }
1550 
1551             if (mCurMethod != null) {
1552                 try {
1553                     mCurMethod.updateExtractedText(token, text);
1554                 } catch (RemoteException e) {
1555                 }
1556             }
1557         }
1558     }
1559 
1560     /**
1561      * Flag for {@link #showSoftInput} to indicate that this is an implicit
1562      * request to show the input window, not as the result of a direct request
1563      * by the user.  The window may not be shown in this case.
1564      */
1565     public static final int SHOW_IMPLICIT = 0x0001;
1566 
1567     /**
1568      * Flag for {@link #showSoftInput} to indicate that the user has forced
1569      * the input method open (such as by long-pressing menu) so it should
1570      * not be closed until they explicitly do so.
1571      */
1572     public static final int SHOW_FORCED = 0x0002;
1573 
1574     /**
1575      * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
1576      * a result receiver: explicitly request that the current input method's
1577      * soft input area be shown to the user, if needed.
1578      *
1579      * @param view The currently focused view, which would like to receive
1580      * soft keyboard input.
1581      * @param flags Provides additional operating flags.  Currently may be
1582      * 0 or have the {@link #SHOW_IMPLICIT} bit set.
1583      */
showSoftInput(View view, int flags)1584     public boolean showSoftInput(View view, int flags) {
1585         // Re-dispatch if there is a context mismatch.
1586         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1587         if (fallbackImm != null) {
1588             return fallbackImm.showSoftInput(view, flags);
1589         }
1590 
1591         return showSoftInput(view, flags, null);
1592     }
1593 
1594     /**
1595      * Flag for the {@link ResultReceiver} result code from
1596      * {@link #showSoftInput(View, int, ResultReceiver)} and
1597      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1598      * state of the soft input window was unchanged and remains shown.
1599      */
1600     public static final int RESULT_UNCHANGED_SHOWN = 0;
1601 
1602     /**
1603      * Flag for the {@link ResultReceiver} result code from
1604      * {@link #showSoftInput(View, int, ResultReceiver)} and
1605      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1606      * state of the soft input window was unchanged and remains hidden.
1607      */
1608     public static final int RESULT_UNCHANGED_HIDDEN = 1;
1609 
1610     /**
1611      * Flag for the {@link ResultReceiver} result code from
1612      * {@link #showSoftInput(View, int, ResultReceiver)} and
1613      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1614      * state of the soft input window changed from hidden to shown.
1615      */
1616     public static final int RESULT_SHOWN = 2;
1617 
1618     /**
1619      * Flag for the {@link ResultReceiver} result code from
1620      * {@link #showSoftInput(View, int, ResultReceiver)} and
1621      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
1622      * state of the soft input window changed from shown to hidden.
1623      */
1624     public static final int RESULT_HIDDEN = 3;
1625 
1626     /**
1627      * Explicitly request that the current input method's soft input area be
1628      * shown to the user, if needed.  Call this if the user interacts with
1629      * your view in such a way that they have expressed they would like to
1630      * start performing input into it.
1631      *
1632      * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1633      * this method can be a long-lived object, because it may not be
1634      * garbage-collected until all the corresponding {@link ResultReceiver}
1635      * objects transferred to different processes get garbage-collected.
1636      * Follow the general patterns to avoid memory leaks in Android.
1637      * Consider to use {@link java.lang.ref.WeakReference} so that application
1638      * logic objects such as {@link android.app.Activity} and {@link Context}
1639      * can be garbage collected regardless of the lifetime of
1640      * {@link ResultReceiver}.
1641      *
1642      * @param view The currently focused view, which would like to receive
1643      * soft keyboard input.
1644      * @param flags Provides additional operating flags.  Currently may be
1645      * 0 or have the {@link #SHOW_IMPLICIT} bit set.
1646      * @param resultReceiver If non-null, this will be called by the IME when
1647      * it has processed your request to tell you what it has done.  The result
1648      * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1649      * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1650      * {@link #RESULT_HIDDEN}.
1651      */
showSoftInput(View view, int flags, ResultReceiver resultReceiver)1652     public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
1653         // Re-dispatch if there is a context mismatch.
1654         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1655         if (fallbackImm != null) {
1656             return fallbackImm.showSoftInput(view, flags, resultReceiver);
1657         }
1658 
1659         checkFocus();
1660         synchronized (mH) {
1661             if (!hasServedByInputMethodLocked(view)) {
1662                 return false;
1663             }
1664 
1665             try {
1666                 return mService.showSoftInput(
1667                         mClient, view.getWindowToken(), flags, resultReceiver);
1668             } catch (RemoteException e) {
1669                 throw e.rethrowFromSystemServer();
1670             }
1671         }
1672     }
1673 
1674     /**
1675      * This method is still kept for a while until android.support.v7.widget.SearchView ver. 26.0
1676      * is publicly released because previous implementations of that class had relied on this method
1677      * via reflection.
1678      *
1679      * @deprecated This is a hidden API. You should never use this.
1680      * @hide
1681      */
1682     @Deprecated
1683     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768499)
showSoftInputUnchecked(int flags, ResultReceiver resultReceiver)1684     public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
1685         synchronized (mH) {
1686             try {
1687                 Log.w(TAG, "showSoftInputUnchecked() is a hidden method, which will be"
1688                         + " removed soon. If you are using android.support.v7.widget.SearchView,"
1689                         + " please update to version 26.0 or newer version.");
1690                 if (mCurRootView == null || mCurRootView.getView() == null) {
1691                     Log.w(TAG, "No current root view, ignoring showSoftInputUnchecked()");
1692                     return;
1693                 }
1694                 mService.showSoftInput(
1695                         mClient, mCurRootView.getView().getWindowToken(), flags, resultReceiver);
1696             } catch (RemoteException e) {
1697                 throw e.rethrowFromSystemServer();
1698             }
1699         }
1700     }
1701 
1702     /**
1703      * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestHideSelf(int)}
1704      * to indicate that the soft input window should only be hidden if it was not explicitly shown
1705      * by the user.
1706      */
1707     public static final int HIDE_IMPLICIT_ONLY = 0x0001;
1708 
1709     /**
1710      * Flag for {@link #hideSoftInputFromWindow} and {@link InputMethodService#requestShowSelf(int)}
1711      * to indicate that the soft input window should normally be hidden, unless it was originally
1712      * shown with {@link #SHOW_FORCED}.
1713      */
1714     public static final int HIDE_NOT_ALWAYS = 0x0002;
1715 
1716     /**
1717      * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
1718      * without a result: request to hide the soft input window from the
1719      * context of the window that is currently accepting input.
1720      *
1721      * @param windowToken The token of the window that is making the request,
1722      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1723      * @param flags Provides additional operating flags.  Currently may be
1724      * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
1725      */
hideSoftInputFromWindow(IBinder windowToken, int flags)1726     public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
1727         return hideSoftInputFromWindow(windowToken, flags, null);
1728     }
1729 
1730     /**
1731      * Request to hide the soft input window from the context of the window
1732      * that is currently accepting input.  This should be called as a result
1733      * of the user doing some actually than fairly explicitly requests to
1734      * have the input window hidden.
1735      *
1736      * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
1737      * this method can be a long-lived object, because it may not be
1738      * garbage-collected until all the corresponding {@link ResultReceiver}
1739      * objects transferred to different processes get garbage-collected.
1740      * Follow the general patterns to avoid memory leaks in Android.
1741      * Consider to use {@link java.lang.ref.WeakReference} so that application
1742      * logic objects such as {@link android.app.Activity} and {@link Context}
1743      * can be garbage collected regardless of the lifetime of
1744      * {@link ResultReceiver}.
1745      *
1746      * @param windowToken The token of the window that is making the request,
1747      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1748      * @param flags Provides additional operating flags.  Currently may be
1749      * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
1750      * @param resultReceiver If non-null, this will be called by the IME when
1751      * it has processed your request to tell you what it has done.  The result
1752      * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
1753      * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
1754      * {@link #RESULT_HIDDEN}.
1755      */
hideSoftInputFromWindow(IBinder windowToken, int flags, ResultReceiver resultReceiver)1756     public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
1757             ResultReceiver resultReceiver) {
1758         checkFocus();
1759         synchronized (mH) {
1760             final View servedView = getServedViewLocked();
1761             if (servedView == null || servedView.getWindowToken() != windowToken) {
1762                 return false;
1763             }
1764 
1765             try {
1766                 return mService.hideSoftInput(mClient, windowToken, flags, resultReceiver);
1767             } catch (RemoteException e) {
1768                 throw e.rethrowFromSystemServer();
1769             }
1770         }
1771     }
1772 
1773     /**
1774      * This method toggles the input method window display.
1775      * If the input window is already displayed, it gets hidden.
1776      * If not the input window will be displayed.
1777      * @param windowToken The token of the window that is making the request,
1778      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
1779      * @param showFlags Provides additional operating flags.  May be
1780      * 0 or have the {@link #SHOW_IMPLICIT},
1781      * {@link #SHOW_FORCED} bit set.
1782      * @param hideFlags Provides additional operating flags.  May be
1783      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1784      * {@link #HIDE_NOT_ALWAYS} bit set.
1785      **/
toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags)1786     public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
1787         synchronized (mH) {
1788             final View servedView = getServedViewLocked();
1789             if (servedView == null || servedView.getWindowToken() != windowToken) {
1790                 return;
1791             }
1792             if (mCurMethod != null) {
1793                 try {
1794                     mCurMethod.toggleSoftInput(showFlags, hideFlags);
1795                 } catch (RemoteException e) {
1796                 }
1797             }
1798         }
1799     }
1800 
1801     /**
1802      * This method toggles the input method window display.
1803      *
1804      * If the input window is already displayed, it gets hidden.
1805      * If not the input window will be displayed.
1806      * @param showFlags Provides additional operating flags.  May be
1807      * 0 or have the {@link #SHOW_IMPLICIT},
1808      * {@link #SHOW_FORCED} bit set.
1809      * @param hideFlags Provides additional operating flags.  May be
1810      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
1811      * {@link #HIDE_NOT_ALWAYS} bit set.
1812      */
toggleSoftInput(int showFlags, int hideFlags)1813     public void toggleSoftInput(int showFlags, int hideFlags) {
1814         if (mCurMethod != null) {
1815             try {
1816                 mCurMethod.toggleSoftInput(showFlags, hideFlags);
1817             } catch (RemoteException e) {
1818             }
1819         }
1820     }
1821 
1822     /**
1823      * If the input method is currently connected to the given view,
1824      * restart it with its new contents.  You should call this when the text
1825      * within your view changes outside of the normal input method or key
1826      * input flow, such as when an application calls TextView.setText().
1827      *
1828      * @param view The view whose text has changed.
1829      */
restartInput(View view)1830     public void restartInput(View view) {
1831         // Re-dispatch if there is a context mismatch.
1832         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
1833         if (fallbackImm != null) {
1834             fallbackImm.restartInput(view);
1835             return;
1836         }
1837 
1838         checkFocus();
1839         synchronized (mH) {
1840             if (!hasServedByInputMethodLocked(view)) {
1841                 return;
1842             }
1843 
1844             mServedConnecting = true;
1845         }
1846 
1847         startInputInner(StartInputReason.APP_CALLED_RESTART_INPUT_API, null, 0, 0, 0);
1848     }
1849 
1850     /**
1851      * Called when {@link DelegateImpl#startInput}, {@link #restartInput(View)},
1852      * {@link #MSG_BIND} or {@link #MSG_UNBIND}.
1853      * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
1854      * background thread may blocked by other methods which already inside {@code mH} lock.
1855      */
startInputInner(@tartInputReason int startInputReason, @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags, @SoftInputModeFlags int softInputMode, int windowFlags)1856     boolean startInputInner(@StartInputReason int startInputReason,
1857             @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
1858             @SoftInputModeFlags int softInputMode, int windowFlags) {
1859         final View view;
1860         synchronized (mH) {
1861             view = getServedViewLocked();
1862 
1863             // Make sure we have a window token for the served view.
1864             if (DEBUG) {
1865                 Log.v(TAG, "Starting input: view=" + dumpViewInfo(view) +
1866                         " reason=" + InputMethodDebug.startInputReasonToString(startInputReason));
1867             }
1868             if (view == null) {
1869                 if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
1870                 return false;
1871             }
1872         }
1873 
1874         if (windowGainingFocus == null) {
1875             windowGainingFocus = view.getWindowToken();
1876             if (windowGainingFocus == null) {
1877                 Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
1878                 return false;
1879             }
1880             startInputFlags = getStartInputFlags(view, startInputFlags);
1881             softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
1882             windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
1883         }
1884 
1885         // Now we need to get an input connection from the served view.
1886         // This is complicated in a couple ways: we can't be holding our lock
1887         // when calling out to the view, and we need to make sure we call into
1888         // the view on the same thread that is driving its view hierarchy.
1889         Handler vh = view.getHandler();
1890         if (vh == null) {
1891             // If the view doesn't have a handler, something has changed out
1892             // from under us, so just close the current input.
1893             // If we don't close the current input, the current input method can remain on the
1894             // screen without a connection.
1895             if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
1896             closeCurrentInput();
1897             return false;
1898         }
1899         if (vh.getLooper() != Looper.myLooper()) {
1900             // The view is running on a different thread than our own, so
1901             // we need to reschedule our work for over there.
1902             if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
1903             vh.post(() -> mDelegate.startInput(startInputReason, null, 0, 0, 0));
1904             return false;
1905         }
1906 
1907         // Okay we are now ready to call into the served view and have it
1908         // do its stuff.
1909         // Life is good: let's hook everything up!
1910         EditorInfo tba = new EditorInfo();
1911         // Note: Use Context#getOpPackageName() rather than Context#getPackageName() so that the
1912         // system can verify the consistency between the uid of this process and package name passed
1913         // from here. See comment of Context#getOpPackageName() for details.
1914         tba.packageName = view.getContext().getOpPackageName();
1915         tba.autofillId = view.getAutofillId();
1916         tba.fieldId = view.getId();
1917         InputConnection ic = view.onCreateInputConnection(tba);
1918         if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
1919 
1920         synchronized (mH) {
1921             // Now that we are locked again, validate that our state hasn't
1922             // changed.
1923             final View servedView = getServedViewLocked();
1924             if (servedView != view || !mServedConnecting) {
1925                 // Something else happened, so abort.
1926                 if (DEBUG) Log.v(TAG,
1927                         "Starting input: finished by someone else. view=" + dumpViewInfo(view)
1928                         + " servedView=" + dumpViewInfo(servedView)
1929                         + " mServedConnecting=" + mServedConnecting);
1930                 return false;
1931             }
1932 
1933             // If we already have a text box, then this view is already
1934             // connected so we want to restart it.
1935             if (mCurrentTextBoxAttribute == null) {
1936                 startInputFlags |= StartInputFlags.INITIAL_CONNECTION;
1937             }
1938 
1939             // Hook 'em up and let 'er rip.
1940             mCurrentTextBoxAttribute = tba;
1941             maybeCallServedViewChangedLocked(tba);
1942             mServedConnecting = false;
1943             if (mServedInputConnectionWrapper != null) {
1944                 mServedInputConnectionWrapper.deactivate();
1945                 mServedInputConnectionWrapper = null;
1946             }
1947             ControlledInputConnectionWrapper servedContext;
1948             final int missingMethodFlags;
1949             if (ic != null) {
1950                 mCursorSelStart = tba.initialSelStart;
1951                 mCursorSelEnd = tba.initialSelEnd;
1952                 mCursorCandStart = -1;
1953                 mCursorCandEnd = -1;
1954                 mCursorRect.setEmpty();
1955                 mCursorAnchorInfo = null;
1956                 final Handler icHandler;
1957                 missingMethodFlags = InputConnectionInspector.getMissingMethodFlags(ic);
1958                 if ((missingMethodFlags & InputConnectionInspector.MissingMethodFlags.GET_HANDLER)
1959                         != 0) {
1960                     // InputConnection#getHandler() is not implemented.
1961                     icHandler = null;
1962                 } else {
1963                     icHandler = ic.getHandler();
1964                 }
1965                 servedContext = new ControlledInputConnectionWrapper(
1966                         icHandler != null ? icHandler.getLooper() : vh.getLooper(), ic, this, view);
1967             } else {
1968                 servedContext = null;
1969                 missingMethodFlags = 0;
1970             }
1971             mServedInputConnectionWrapper = servedContext;
1972 
1973             try {
1974                 if (DEBUG) Log.v(TAG, "START INPUT: view=" + dumpViewInfo(view) + " ic="
1975                         + ic + " tba=" + tba + " startInputFlags="
1976                         + InputMethodDebug.startInputFlagsToString(startInputFlags));
1977                 final InputBindResult res = mService.startInputOrWindowGainedFocus(
1978                         startInputReason, mClient, windowGainingFocus, startInputFlags,
1979                         softInputMode, windowFlags, tba, servedContext, missingMethodFlags,
1980                         view.getContext().getApplicationInfo().targetSdkVersion);
1981                 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
1982                 if (res == null) {
1983                     Log.wtf(TAG, "startInputOrWindowGainedFocus must not return"
1984                             + " null. startInputReason="
1985                             + InputMethodDebug.startInputReasonToString(startInputReason)
1986                             + " editorInfo=" + tba
1987                             + " startInputFlags="
1988                             + InputMethodDebug.startInputFlagsToString(startInputFlags));
1989                     return false;
1990                 }
1991                 mActivityViewToScreenMatrix = res.getActivityViewToScreenMatrix();
1992                 if (res.id != null) {
1993                     setInputChannelLocked(res.channel);
1994                     mBindSequence = res.sequence;
1995                     mCurMethod = res.method;
1996                     mCurId = res.id;
1997                 } else if (res.channel != null && res.channel != mCurChannel) {
1998                     res.channel.dispose();
1999                 }
2000                 switch (res.result) {
2001                     case InputBindResult.ResultCode.ERROR_NOT_IME_TARGET_WINDOW:
2002                         mRestartOnNextWindowFocus = true;
2003                         break;
2004                 }
2005                 if (mCurMethod != null && mCompletions != null) {
2006                     try {
2007                         mCurMethod.displayCompletions(mCompletions);
2008                     } catch (RemoteException e) {
2009                     }
2010                 }
2011             } catch (RemoteException e) {
2012                 Log.w(TAG, "IME died: " + mCurId, e);
2013             }
2014         }
2015 
2016         return true;
2017     }
2018 
2019     /**
2020      * An empty method only to avoid crashes of apps that call this method via reflection and do not
2021      * handle {@link NoSuchMethodException} in a graceful manner.
2022      *
2023      * @deprecated This is an empty method.  No framework method must call this method.
2024      * @hide
2025      */
2026     @Deprecated
2027     @UnsupportedAppUsage(trackingBug = 37122102, maxTargetSdk = Build.VERSION_CODES.Q,
2028             publicAlternatives = "{@code androidx.activity.ComponentActivity}")
windowDismissed(IBinder appWindowToken)2029     public void windowDismissed(IBinder appWindowToken) {
2030         // Intentionally empty.
2031         //
2032         // It seems that some applications call this method via reflection to null clear the
2033         // following fields that used to exist in InputMethodManager:
2034         //  * InputMethodManager#mCurRootView
2035         //  * InputMethodManager#mServedView
2036         //  * InputMethodManager#mNextServedView
2037         // so that these objects can be garbage-collected when an Activity gets dismissed.
2038         //
2039         // It is indeed true that older versions of InputMethodManager had issues that prevented
2040         // these fields from being null-cleared when it should have been, but the understanding of
2041         // the engineering team is that all known issues have already been fixed as of Android 10.
2042         //
2043         // For older devices, developers can work around the object leaks by using
2044         // androidx.activity.ComponentActivity.
2045         // See https://issuetracker.google.com/u/1/issues/37122102 for details.
2046         //
2047         // If you believe InputMethodManager is leaking objects in API 24 or any later version,
2048         // please file a bug at https://issuetracker.google.com/issues/new?component=192705.
2049     }
2050 
getStartInputFlags(View focusedView, int startInputFlags)2051     private int getStartInputFlags(View focusedView, int startInputFlags) {
2052         startInputFlags |= StartInputFlags.VIEW_HAS_FOCUS;
2053         if (focusedView.onCheckIsTextEditor()) {
2054             startInputFlags |= StartInputFlags.IS_TEXT_EDITOR;
2055         }
2056         return startInputFlags;
2057     }
2058 
2059     /**
2060      * Check the next served view from {@link ImeFocusController} if needs to start input.
2061      * Note that this method should *NOT* be called inside of {@code mH} lock to prevent start input
2062      * background thread may blocked by other methods which already inside {@code mH} lock.
2063      * @hide
2064      */
2065     @UnsupportedAppUsage
checkFocus()2066     public void checkFocus() {
2067         final ImeFocusController controller = getFocusController();
2068         if (controller != null) {
2069             controller.checkFocus(false /* forceNewFocus */, true /* startInput */);
2070         }
2071     }
2072 
2073     @UnsupportedAppUsage
closeCurrentInput()2074     void closeCurrentInput() {
2075         synchronized (mH) {
2076             if (mCurRootView == null || mCurRootView.getView() == null) {
2077                 Log.w(TAG, "No current root view, ignoring closeCurrentInput()");
2078                 return;
2079             }
2080             try {
2081                 mService.hideSoftInput(
2082                         mClient, mCurRootView.getView().getWindowToken(), HIDE_NOT_ALWAYS, null);
2083             } catch (RemoteException e) {
2084                 throw e.rethrowFromSystemServer();
2085             }
2086         }
2087     }
2088 
2089     /**
2090      * Register for IME state callbacks and applying visibility in
2091      * {@link android.view.ImeInsetsSourceConsumer}.
2092      * @hide
2093      */
registerImeConsumer(@onNull ImeInsetsSourceConsumer imeInsetsConsumer)2094     public void registerImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2095         if (imeInsetsConsumer == null) {
2096             throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2097         }
2098 
2099         synchronized (mH) {
2100             mImeInsetsConsumer = imeInsetsConsumer;
2101         }
2102     }
2103 
2104     /**
2105      * Unregister for IME state callbacks and applying visibility in
2106      * {@link android.view.ImeInsetsSourceConsumer}.
2107      * @hide
2108      */
unregisterImeConsumer(@onNull ImeInsetsSourceConsumer imeInsetsConsumer)2109     public void unregisterImeConsumer(@NonNull ImeInsetsSourceConsumer imeInsetsConsumer) {
2110         if (imeInsetsConsumer == null) {
2111             throw new IllegalStateException("ImeInsetsSourceConsumer cannot be null.");
2112         }
2113 
2114         synchronized (mH) {
2115             if (mImeInsetsConsumer == imeInsetsConsumer) {
2116                 mImeInsetsConsumer = null;
2117             }
2118         }
2119     }
2120 
2121     /**
2122      * Call showSoftInput with currently focused view.
2123      *
2124      * @param windowToken the window from which this request originates. If this doesn't match the
2125      *                    currently served view, the request is ignored and returns {@code false}.
2126      *
2127      * @return {@code true} if IME can (eventually) be shown, {@code false} otherwise.
2128      * @hide
2129      */
requestImeShow(IBinder windowToken)2130     public boolean requestImeShow(IBinder windowToken) {
2131         synchronized (mH) {
2132             final View servedView = getServedViewLocked();
2133             if (servedView == null || servedView.getWindowToken() != windowToken) {
2134                 return false;
2135             }
2136             showSoftInput(servedView, 0 /* flags */, null /* resultReceiver */);
2137             return true;
2138         }
2139     }
2140 
2141     /**
2142      * Notify IME directly that it is no longer visible.
2143      *
2144      * @param windowToken the window from which this request originates. If this doesn't match the
2145      *                    currently served view, the request is ignored.
2146      * @hide
2147      */
notifyImeHidden(IBinder windowToken)2148     public void notifyImeHidden(IBinder windowToken) {
2149         synchronized (mH) {
2150             try {
2151                 if (mCurMethod != null && mCurRootView != null
2152                         && mCurRootView.getWindowToken() == windowToken) {
2153                     mCurMethod.notifyImeHidden();
2154                 }
2155             } catch (RemoteException re) {
2156             }
2157         }
2158     }
2159 
2160     /**
2161      * Notify IME directly to remove surface as it is no longer visible.
2162      * @param windowToken The client window token that requests the IME to remove its surface.
2163      * @hide
2164      */
removeImeSurface(IBinder windowToken)2165     public void removeImeSurface(IBinder windowToken) {
2166         synchronized (mH) {
2167             try {
2168                 mService.removeImeSurfaceFromWindow(windowToken);
2169             } catch (RemoteException e) {
2170                 throw e.rethrowFromSystemServer();
2171             }
2172         }
2173     }
2174 
2175     /**
2176      * Report the current selection range.
2177      *
2178      * <p><strong>Editor authors</strong>, you need to call this method whenever
2179      * the cursor moves in your editor. Remember that in addition to doing this, your
2180      * editor needs to always supply current cursor values in
2181      * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
2182      * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
2183      * called, which happens whenever the keyboard shows up or the focus changes
2184      * to a text field, among other cases.</p>
2185      */
updateSelection(View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd)2186     public void updateSelection(View view, int selStart, int selEnd,
2187             int candidatesStart, int candidatesEnd) {
2188         // Re-dispatch if there is a context mismatch.
2189         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2190         if (fallbackImm != null) {
2191             fallbackImm.updateSelection(view, selStart, selEnd, candidatesStart, candidatesEnd);
2192             return;
2193         }
2194 
2195         checkFocus();
2196         synchronized (mH) {
2197             if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2198                     || mCurMethod == null) {
2199                 return;
2200             }
2201 
2202             if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
2203                     || mCursorCandStart != candidatesStart
2204                     || mCursorCandEnd != candidatesEnd) {
2205                 if (DEBUG) Log.d(TAG, "updateSelection");
2206 
2207                 try {
2208                     if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
2209                     final int oldSelStart = mCursorSelStart;
2210                     final int oldSelEnd = mCursorSelEnd;
2211                     // Update internal values before sending updateSelection to the IME, because
2212                     // if it changes the text within its onUpdateSelection handler in a way that
2213                     // does not move the cursor we don't want to call it again with the same values.
2214                     mCursorSelStart = selStart;
2215                     mCursorSelEnd = selEnd;
2216                     mCursorCandStart = candidatesStart;
2217                     mCursorCandEnd = candidatesEnd;
2218                     mCurMethod.updateSelection(oldSelStart, oldSelEnd,
2219                             selStart, selEnd, candidatesStart, candidatesEnd);
2220                 } catch (RemoteException e) {
2221                     Log.w(TAG, "IME died: " + mCurId, e);
2222                 }
2223             }
2224         }
2225     }
2226 
2227     /**
2228      * Notify the event when the user tapped or clicked the text view.
2229      *
2230      * @param view {@link View} which is being clicked.
2231      * @see InputMethodService#onViewClicked(boolean)
2232      * @deprecated The semantics of this method can never be defined well for composite {@link View}
2233      *             that works as a giant "Canvas", which can host its own UI hierarchy and sub focus
2234      *             state. {@link android.webkit.WebView} is a good example. Application / IME
2235      *             developers should not rely on this method.
2236      */
2237     @Deprecated
viewClicked(View view)2238     public void viewClicked(View view) {
2239         // Re-dispatch if there is a context mismatch.
2240         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2241         if (fallbackImm != null) {
2242             fallbackImm.viewClicked(view);
2243             return;
2244         }
2245 
2246         final View servedView;
2247         final View nextServedView;
2248         synchronized (mH) {
2249             servedView = getServedViewLocked();
2250             nextServedView = getNextServedViewLocked();
2251         }
2252         final boolean focusChanged = servedView != nextServedView;
2253         checkFocus();
2254         synchronized (mH) {
2255             if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2256                     || mCurMethod == null) {
2257                 return;
2258             }
2259             try {
2260                 if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
2261                 mCurMethod.viewClicked(focusChanged);
2262             } catch (RemoteException e) {
2263                 Log.w(TAG, "IME died: " + mCurId, e);
2264             }
2265         }
2266     }
2267 
2268     /**
2269      * Return true if the current input method wants to watch the location
2270      * of the input editor's cursor in its window.
2271      *
2272      * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
2273      */
2274     @Deprecated
isWatchingCursor(View view)2275     public boolean isWatchingCursor(View view) {
2276         return false;
2277     }
2278 
2279     /**
2280      * Return true if the current input method wants to be notified when cursor/anchor location
2281      * is changed.
2282      *
2283      * @hide
2284      */
2285     @UnsupportedAppUsage
isCursorAnchorInfoEnabled()2286     public boolean isCursorAnchorInfoEnabled() {
2287         synchronized (mH) {
2288             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
2289                     InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
2290             final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
2291                     InputConnection.CURSOR_UPDATE_MONITOR) != 0;
2292             return isImmediate || isMonitoring;
2293         }
2294     }
2295 
2296     /**
2297      * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
2298      *
2299      * @hide
2300      */
2301     @UnsupportedAppUsage
setUpdateCursorAnchorInfoMode(int flags)2302     public void setUpdateCursorAnchorInfoMode(int flags) {
2303         synchronized (mH) {
2304             mRequestUpdateCursorAnchorInfoMonitorMode = flags;
2305         }
2306     }
2307 
2308     /**
2309      * Report the current cursor location in its window.
2310      *
2311      * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
2312      */
2313     @Deprecated
updateCursor(View view, int left, int top, int right, int bottom)2314     public void updateCursor(View view, int left, int top, int right, int bottom) {
2315         // Re-dispatch if there is a context mismatch.
2316         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2317         if (fallbackImm != null) {
2318             fallbackImm.updateCursor(view, left, top, right, bottom);
2319             return;
2320         }
2321 
2322         checkFocus();
2323         synchronized (mH) {
2324             if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2325                     || mCurMethod == null) {
2326                 return;
2327             }
2328 
2329             mTmpCursorRect.set(left, top, right, bottom);
2330             if (!mCursorRect.equals(mTmpCursorRect)) {
2331                 if (DEBUG) Log.d(TAG, "updateCursor");
2332 
2333                 try {
2334                     if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
2335                     mCurMethod.updateCursor(mTmpCursorRect);
2336                     mCursorRect.set(mTmpCursorRect);
2337                 } catch (RemoteException e) {
2338                     Log.w(TAG, "IME died: " + mCurId, e);
2339                 }
2340             }
2341         }
2342     }
2343 
2344     /**
2345      * Report positional change of the text insertion point and/or characters in the composition
2346      * string.
2347      */
updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo)2348     public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
2349         if (view == null || cursorAnchorInfo == null) {
2350             return;
2351         }
2352         // Re-dispatch if there is a context mismatch.
2353         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2354         if (fallbackImm != null) {
2355             fallbackImm.updateCursorAnchorInfo(view, cursorAnchorInfo);
2356             return;
2357         }
2358 
2359         checkFocus();
2360         synchronized (mH) {
2361             if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2362                     || mCurMethod == null) {
2363                 return;
2364             }
2365             // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
2366             // not been changed from the previous call.
2367             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
2368                     InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
2369             if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
2370                 // TODO: Consider always emitting this message once we have addressed redundant
2371                 // calls of this method from android.widget.Editor.
2372                 if (DEBUG) {
2373                     Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
2374                             + cursorAnchorInfo);
2375                 }
2376                 return;
2377             }
2378             if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
2379             try {
2380                 if (mActivityViewToScreenMatrix != null) {
2381                     mCurMethod.updateCursorAnchorInfo(
2382                             CursorAnchorInfo.createForAdditionalParentMatrix(
2383                                     cursorAnchorInfo, mActivityViewToScreenMatrix));
2384                 } else {
2385                     mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
2386                 }
2387                 mCursorAnchorInfo = cursorAnchorInfo;
2388                 // Clear immediate bit (if any).
2389                 mRequestUpdateCursorAnchorInfoMonitorMode &=
2390                         ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
2391             } catch (RemoteException e) {
2392                 Log.w(TAG, "IME died: " + mCurId, e);
2393             }
2394         }
2395     }
2396 
2397     /**
2398      * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
2399      * InputMethodSession.appPrivateCommand()} on the current Input Method.
2400      * @param view Optional View that is sending the command, or null if
2401      * you want to send the command regardless of the view that is attached
2402      * to the input method.
2403      * @param action Name of the command to be performed.  This <em>must</em>
2404      * be a scoped name, i.e. prefixed with a package name you own, so that
2405      * different developers will not create conflicting commands.
2406      * @param data Any data to include with the command.
2407      */
sendAppPrivateCommand(View view, String action, Bundle data)2408     public void sendAppPrivateCommand(View view, String action, Bundle data) {
2409         // Re-dispatch if there is a context mismatch.
2410         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(view);
2411         if (fallbackImm != null) {
2412             fallbackImm.sendAppPrivateCommand(view, action, data);
2413             return;
2414         }
2415 
2416         checkFocus();
2417         synchronized (mH) {
2418             if (!hasServedByInputMethodLocked(view) || mCurrentTextBoxAttribute == null
2419                     || mCurMethod == null) {
2420                 return;
2421             }
2422             try {
2423                 if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
2424                 mCurMethod.appPrivateCommand(action, data);
2425             } catch (RemoteException e) {
2426                 Log.w(TAG, "IME died: " + mCurId, e);
2427             }
2428         }
2429     }
2430 
2431     /**
2432      * Force switch to a new input method component. This can only be called
2433      * from an application or a service which has a token of the currently active input method.
2434      *
2435      * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, the undocumented behavior that
2436      * token can be {@code null} when the caller has
2437      * {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} is deprecated. Instead, update
2438      * {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2439      * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2440      *
2441      * @param token Supplies the identifying token given to an input method
2442      * when it was started, which allows it to perform this operation on
2443      * itself.
2444      * @param id The unique identifier for the new input method to be switched to.
2445      * @deprecated Use {@link InputMethodService#switchInputMethod(String)}
2446      * instead. This method was intended for IME developers who should be accessing APIs through
2447      * the service. APIs in this class are intended for app developers interacting with the IME.
2448      */
2449     @Deprecated
setInputMethod(IBinder token, String id)2450     public void setInputMethod(IBinder token, String id) {
2451         if (token == null) {
2452             // There are still some system components that rely on this undocumented behavior
2453             // regarding null IME token with WRITE_SECURE_SETTINGS.  Provide a fallback logic as a
2454             // temporary remedy.
2455             if (id == null) {
2456                 return;
2457             }
2458             if (Process.myUid() == Process.SYSTEM_UID) {
2459                 Log.w(TAG, "System process should not be calling setInputMethod() because almost "
2460                         + "always it is a bug under multi-user / multi-profile environment. "
2461                         + "Consider interacting with InputMethodManagerService directly via "
2462                         + "LocalServices.");
2463                 return;
2464             }
2465             final Context fallbackContext = ActivityThread.currentApplication();
2466             if (fallbackContext == null) {
2467                 return;
2468             }
2469             if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2470                     != PackageManager.PERMISSION_GRANTED) {
2471                 return;
2472             }
2473             final List<InputMethodInfo> imis = getEnabledInputMethodList();
2474             final int numImis = imis.size();
2475             boolean found = false;
2476             for (int i = 0; i < numImis; ++i) {
2477                 final InputMethodInfo imi = imis.get(i);
2478                 if (id.equals(imi.getId())) {
2479                     found = true;
2480                     break;
2481                 }
2482             }
2483             if (!found) {
2484                 Log.e(TAG, "Ignoring setInputMethod(null, " + id + ") because the specified "
2485                         + "id not found in enabled IMEs.");
2486                 return;
2487             }
2488             Log.w(TAG, "The undocumented behavior that setInputMethod() accepts null token "
2489                     + "when the caller has WRITE_SECURE_SETTINGS is deprecated. This behavior may "
2490                     + "be completely removed in a future version.  Update secure settings directly "
2491                     + "instead.");
2492             final ContentResolver resolver = fallbackContext.getContentResolver();
2493             Settings.Secure.putInt(resolver, Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE,
2494                     NOT_A_SUBTYPE_ID);
2495             Settings.Secure.putString(resolver, Settings.Secure.DEFAULT_INPUT_METHOD, id);
2496             return;
2497         }
2498         InputMethodPrivilegedOperationsRegistry.get(token).setInputMethod(id);
2499     }
2500 
2501     /**
2502      * Force switch to a new input method and subtype. This can only be called
2503      * from an application or a service which has a token of the currently active input method.
2504      *
2505      * <p>On Android {@link Build.VERSION_CODES#Q} and later devices, {@code token} cannot be
2506      * {@code null} even with {@link android.Manifest.permission#WRITE_SECURE_SETTINGS}. Instead,
2507      * update {@link android.provider.Settings.Secure#DEFAULT_INPUT_METHOD} and
2508      * {@link android.provider.Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE} directly.</p>
2509      *
2510      * @param token Supplies the identifying token given to an input method
2511      * when it was started, which allows it to perform this operation on
2512      * itself.
2513      * @param id The unique identifier for the new input method to be switched to.
2514      * @param subtype The new subtype of the new input method to be switched to.
2515      * @deprecated Use
2516      * {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}
2517      * instead. This method was intended for IME developers who should be accessing APIs through
2518      * the service. APIs in this class are intended for app developers interacting with the IME.
2519      */
2520     @Deprecated
setInputMethodAndSubtype(@onNull IBinder token, String id, InputMethodSubtype subtype)2521     public void setInputMethodAndSubtype(@NonNull IBinder token, String id,
2522             InputMethodSubtype subtype) {
2523         if (token == null) {
2524             Log.e(TAG, "setInputMethodAndSubtype() does not accept null token on Android Q "
2525                     + "and later.");
2526             return;
2527         }
2528         InputMethodPrivilegedOperationsRegistry.get(token).setInputMethodAndSubtype(id, subtype);
2529     }
2530 
2531     /**
2532      * Close/hide the input method's soft input area, so the user no longer
2533      * sees it or can interact with it.  This can only be called
2534      * from the currently active input method, as validated by the given token.
2535      *
2536      * @param token Supplies the identifying token given to an input method
2537      * when it was started, which allows it to perform this operation on
2538      * itself.
2539      * @param flags Provides additional operating flags.  Currently may be
2540      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
2541      * {@link #HIDE_NOT_ALWAYS} bit set.
2542      * @deprecated Use {@link InputMethodService#requestHideSelf(int)} instead. This method was
2543      * intended for IME developers who should be accessing APIs through the service. APIs in this
2544      * class are intended for app developers interacting with the IME.
2545      */
2546     @Deprecated
hideSoftInputFromInputMethod(IBinder token, int flags)2547     public void hideSoftInputFromInputMethod(IBinder token, int flags) {
2548         InputMethodPrivilegedOperationsRegistry.get(token).hideMySoftInput(flags);
2549     }
2550 
2551     /**
2552      * Show the input method's soft input area, so the user
2553      * sees the input method window and can interact with it.
2554      * This can only be called from the currently active input method,
2555      * as validated by the given token.
2556      *
2557      * @param token Supplies the identifying token given to an input method
2558      * when it was started, which allows it to perform this operation on
2559      * itself.
2560      * @param flags Provides additional operating flags.  Currently may be
2561      * 0 or have the {@link #SHOW_IMPLICIT} or
2562      * {@link #SHOW_FORCED} bit set.
2563      * @deprecated Use {@link InputMethodService#requestShowSelf(int)} instead. This method was
2564      * intended for IME developers who should be accessing APIs through the service. APIs in this
2565      * class are intended for app developers interacting with the IME.
2566      */
2567     @Deprecated
showSoftInputFromInputMethod(IBinder token, int flags)2568     public void showSoftInputFromInputMethod(IBinder token, int flags) {
2569         InputMethodPrivilegedOperationsRegistry.get(token).showMySoftInput(flags);
2570     }
2571 
2572     /**
2573      * Dispatches an input event to the IME.
2574      *
2575      * Returns {@link #DISPATCH_HANDLED} if the event was handled.
2576      * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
2577      * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
2578      * callback will be invoked later.
2579      *
2580      * @hide
2581      */
dispatchInputEvent(InputEvent event, Object token, FinishedInputEventCallback callback, Handler handler)2582     public int dispatchInputEvent(InputEvent event, Object token,
2583             FinishedInputEventCallback callback, Handler handler) {
2584         synchronized (mH) {
2585             if (mCurMethod != null) {
2586                 if (event instanceof KeyEvent) {
2587                     KeyEvent keyEvent = (KeyEvent)event;
2588                     if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
2589                             && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
2590                             && keyEvent.getRepeatCount() == 0) {
2591                         showInputMethodPickerLocked();
2592                         return DISPATCH_HANDLED;
2593                     }
2594                 }
2595 
2596                 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
2597 
2598                 PendingEvent p = obtainPendingEventLocked(
2599                         event, token, mCurId, callback, handler);
2600                 if (mMainLooper.isCurrentThread()) {
2601                     // Already running on the IMM thread so we can send the event immediately.
2602                     return sendInputEventOnMainLooperLocked(p);
2603                 }
2604 
2605                 // Post the event to the IMM thread.
2606                 Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
2607                 msg.setAsynchronous(true);
2608                 mH.sendMessage(msg);
2609                 return DISPATCH_IN_PROGRESS;
2610             }
2611         }
2612         return DISPATCH_NOT_HANDLED;
2613     }
2614 
2615     /**
2616      * Provides the default implementation of {@link InputConnection#sendKeyEvent(KeyEvent)}, which
2617      * is expected to dispatch an keyboard event sent from the IME to an appropriate event target
2618      * depending on the given {@link View} and the current focus state.
2619      *
2620      * <p>CAUTION: This method is provided only for the situation where
2621      * {@link InputConnection#sendKeyEvent(KeyEvent)} needs to be implemented without relying on
2622      * {@link BaseInputConnection}. Do not use this API for anything else.</p>
2623      *
2624      * @param targetView the default target view. If {@code null} is specified, then this method
2625      * tries to find a good event target based on the current focus state.
2626      * @param event the key event to be dispatched.
2627      */
dispatchKeyEventFromInputMethod(@ullable View targetView, @NonNull KeyEvent event)2628     public void dispatchKeyEventFromInputMethod(@Nullable View targetView,
2629             @NonNull KeyEvent event) {
2630         // Re-dispatch if there is a context mismatch.
2631         final InputMethodManager fallbackImm = getFallbackInputMethodManagerIfNecessary(targetView);
2632         if (fallbackImm != null) {
2633             fallbackImm.dispatchKeyEventFromInputMethod(targetView, event);
2634             return;
2635         }
2636 
2637         synchronized (mH) {
2638             ViewRootImpl viewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
2639             if (viewRootImpl == null) {
2640                 final View servedView = getServedViewLocked();
2641                 if (servedView != null) {
2642                     viewRootImpl = servedView.getViewRootImpl();
2643                 }
2644             }
2645             if (viewRootImpl != null) {
2646                 viewRootImpl.dispatchKeyFromIme(event);
2647             }
2648         }
2649     }
2650 
2651     // Must be called on the main looper
sendInputEventAndReportResultOnMainLooper(PendingEvent p)2652     void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
2653         final boolean handled;
2654         synchronized (mH) {
2655             int result = sendInputEventOnMainLooperLocked(p);
2656             if (result == DISPATCH_IN_PROGRESS) {
2657                 return;
2658             }
2659 
2660             handled = (result == DISPATCH_HANDLED);
2661         }
2662 
2663         invokeFinishedInputEventCallback(p, handled);
2664     }
2665 
2666     // Must be called on the main looper
sendInputEventOnMainLooperLocked(PendingEvent p)2667     int sendInputEventOnMainLooperLocked(PendingEvent p) {
2668         if (mCurChannel != null) {
2669             if (mCurSender == null) {
2670                 mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
2671             }
2672 
2673             final InputEvent event = p.mEvent;
2674             final int seq = event.getSequenceNumber();
2675             if (mCurSender.sendInputEvent(seq, event)) {
2676                 mPendingEvents.put(seq, p);
2677                 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
2678                         mPendingEvents.size());
2679 
2680                 Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, seq, 0, p);
2681                 msg.setAsynchronous(true);
2682                 mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
2683                 return DISPATCH_IN_PROGRESS;
2684             }
2685 
2686             Log.w(TAG, "Unable to send input event to IME: "
2687                     + mCurId + " dropping: " + event);
2688         }
2689         return DISPATCH_NOT_HANDLED;
2690     }
2691 
finishedInputEvent(int seq, boolean handled, boolean timeout)2692     void finishedInputEvent(int seq, boolean handled, boolean timeout) {
2693         final PendingEvent p;
2694         synchronized (mH) {
2695             int index = mPendingEvents.indexOfKey(seq);
2696             if (index < 0) {
2697                 return; // spurious, event already finished or timed out
2698             }
2699 
2700             p = mPendingEvents.valueAt(index);
2701             mPendingEvents.removeAt(index);
2702             Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
2703 
2704             if (timeout) {
2705                 Log.w(TAG, "Timeout waiting for IME to handle input event after "
2706                         + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
2707             } else {
2708                 mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
2709             }
2710         }
2711 
2712         invokeFinishedInputEventCallback(p, handled);
2713     }
2714 
2715     // Assumes the event has already been removed from the queue.
invokeFinishedInputEventCallback(PendingEvent p, boolean handled)2716     void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
2717         p.mHandled = handled;
2718         if (p.mHandler.getLooper().isCurrentThread()) {
2719             // Already running on the callback handler thread so we can send the
2720             // callback immediately.
2721             p.run();
2722         } else {
2723             // Post the event to the callback handler thread.
2724             // In this case, the callback will be responsible for recycling the event.
2725             Message msg = Message.obtain(p.mHandler, p);
2726             msg.setAsynchronous(true);
2727             msg.sendToTarget();
2728         }
2729     }
2730 
flushPendingEventsLocked()2731     private void flushPendingEventsLocked() {
2732         mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
2733 
2734         final int count = mPendingEvents.size();
2735         for (int i = 0; i < count; i++) {
2736             int seq = mPendingEvents.keyAt(i);
2737             Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
2738             msg.setAsynchronous(true);
2739             msg.sendToTarget();
2740         }
2741     }
2742 
obtainPendingEventLocked(InputEvent event, Object token, String inputMethodId, FinishedInputEventCallback callback, Handler handler)2743     private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
2744             String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
2745         PendingEvent p = mPendingEventPool.acquire();
2746         if (p == null) {
2747             p = new PendingEvent();
2748         }
2749         p.mEvent = event;
2750         p.mToken = token;
2751         p.mInputMethodId = inputMethodId;
2752         p.mCallback = callback;
2753         p.mHandler = handler;
2754         return p;
2755     }
2756 
recyclePendingEventLocked(PendingEvent p)2757     private void recyclePendingEventLocked(PendingEvent p) {
2758         p.recycle();
2759         mPendingEventPool.release(p);
2760     }
2761 
2762     /**
2763      * Show IME picker popup window.
2764      *
2765      * <p>Requires the {@link PackageManager#FEATURE_INPUT_METHODS} feature which can be detected
2766      * using {@link PackageManager#hasSystemFeature(String)}.
2767      */
showInputMethodPicker()2768     public void showInputMethodPicker() {
2769         synchronized (mH) {
2770             showInputMethodPickerLocked();
2771         }
2772     }
2773 
2774     /**
2775      * Shows the input method chooser dialog from system.
2776      *
2777      * @param showAuxiliarySubtypes Set true to show auxiliary input methods.
2778      * @param displayId The ID of the display where the chooser dialog should be shown.
2779      * @hide
2780      */
2781     @RequiresPermission(WRITE_SECURE_SETTINGS)
showInputMethodPickerFromSystem(boolean showAuxiliarySubtypes, int displayId)2782     public void showInputMethodPickerFromSystem(boolean showAuxiliarySubtypes, int displayId) {
2783         final int mode = showAuxiliarySubtypes
2784                 ? SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES
2785                 : SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES;
2786         try {
2787             mService.showInputMethodPickerFromSystem(mClient, mode, displayId);
2788         } catch (RemoteException e) {
2789             throw e.rethrowFromSystemServer();
2790         }
2791     }
2792 
showInputMethodPickerLocked()2793     private void showInputMethodPickerLocked() {
2794         try {
2795             mService.showInputMethodPickerFromClient(mClient, SHOW_IM_PICKER_MODE_AUTO);
2796         } catch (RemoteException e) {
2797             throw e.rethrowFromSystemServer();
2798         }
2799     }
2800 
2801     /**
2802      * A test API for CTS to make sure that {@link #showInputMethodPicker()} works as expected.
2803      *
2804      * <p>When customizing the implementation of {@link #showInputMethodPicker()} API, make sure
2805      * that this test API returns when and only while and only while
2806      * {@link #showInputMethodPicker()} is showing UI. Otherwise your OS implementation may not
2807      * pass CTS.</p>
2808      *
2809      * @return {@code true} while and only while {@link #showInputMethodPicker()} is showing UI.
2810      * @hide
2811      */
2812     @TestApi
isInputMethodPickerShown()2813     public boolean isInputMethodPickerShown() {
2814         try {
2815             return mService.isInputMethodPickerShownForTest();
2816         } catch (RemoteException e) {
2817             throw e.rethrowFromSystemServer();
2818         }
2819     }
2820 
2821     /**
2822      * Show the settings for enabling subtypes of the specified input method.
2823      *
2824      * @param imiId An input method, whose subtypes settings will be shown. If imiId is null,
2825      * subtypes of all input methods will be shown.
2826      */
showInputMethodAndSubtypeEnabler(String imiId)2827     public void showInputMethodAndSubtypeEnabler(String imiId) {
2828         try {
2829             mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
2830         } catch (RemoteException e) {
2831             throw e.rethrowFromSystemServer();
2832         }
2833     }
2834 
2835     /**
2836      * Returns the current input method subtype. This subtype is one of the subtypes in
2837      * the current input method. This method returns null when the current input method doesn't
2838      * have any input method subtype.
2839      */
getCurrentInputMethodSubtype()2840     public InputMethodSubtype getCurrentInputMethodSubtype() {
2841         try {
2842             return mService.getCurrentInputMethodSubtype();
2843         } catch (RemoteException e) {
2844             throw e.rethrowFromSystemServer();
2845         }
2846     }
2847 
2848     /**
2849      * Switch to a new input method subtype of the current input method.
2850      * @param subtype A new input method subtype to switch.
2851      * @return true if the current subtype was successfully switched. When the specified subtype is
2852      * null, this method returns false.
2853      * @deprecated If the calling process is an IME, use
2854      *             {@link InputMethodService#switchInputMethod(String, InputMethodSubtype)}, which
2855      *             does not require any permission as long as the caller is the current IME.
2856      *             If the calling process is some privileged app that already has
2857      *             {@link android.Manifest.permission#WRITE_SECURE_SETTINGS} permission, just
2858      *             directly update {@link Settings.Secure#SELECTED_INPUT_METHOD_SUBTYPE}.
2859      */
2860     @Deprecated
2861     @RequiresPermission(WRITE_SECURE_SETTINGS)
setCurrentInputMethodSubtype(InputMethodSubtype subtype)2862     public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
2863         if (Process.myUid() == Process.SYSTEM_UID) {
2864             Log.w(TAG, "System process should not call setCurrentInputMethodSubtype() because "
2865                     + "almost always it is a bug under multi-user / multi-profile environment. "
2866                     + "Consider directly interacting with InputMethodManagerService "
2867                     + "via LocalServices.");
2868             return false;
2869         }
2870         if (subtype == null) {
2871             // See the JavaDoc. This is how this method has worked.
2872             return false;
2873         }
2874         final Context fallbackContext = ActivityThread.currentApplication();
2875         if (fallbackContext == null) {
2876             return false;
2877         }
2878         if (fallbackContext.checkSelfPermission(WRITE_SECURE_SETTINGS)
2879                 != PackageManager.PERMISSION_GRANTED) {
2880             return false;
2881         }
2882         final ContentResolver contentResolver = fallbackContext.getContentResolver();
2883         final String imeId = Settings.Secure.getString(contentResolver,
2884                 Settings.Secure.DEFAULT_INPUT_METHOD);
2885         if (ComponentName.unflattenFromString(imeId) == null) {
2886             // Null or invalid IME ID format.
2887             return false;
2888         }
2889         final List<InputMethodSubtype> enabledSubtypes;
2890         try {
2891             enabledSubtypes = mService.getEnabledInputMethodSubtypeList(imeId, true);
2892         } catch (RemoteException e) {
2893             return false;
2894         }
2895         final int numSubtypes = enabledSubtypes.size();
2896         for (int i = 0; i < numSubtypes; ++i) {
2897             final InputMethodSubtype enabledSubtype = enabledSubtypes.get(i);
2898             if (enabledSubtype.equals(subtype)) {
2899                 Settings.Secure.putInt(contentResolver,
2900                         Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE, enabledSubtype.hashCode());
2901                 return true;
2902             }
2903         }
2904         return false;
2905     }
2906 
2907     /**
2908      * Notify that a user took some action with this input method.
2909      *
2910      * @deprecated Just kept to avoid possible app compat issue.
2911      * @hide
2912      */
2913     @Deprecated
2914     @UnsupportedAppUsage(trackingBug = 114740982, maxTargetSdk = Build.VERSION_CODES.P)
notifyUserAction()2915     public void notifyUserAction() {
2916         Log.w(TAG, "notifyUserAction() is a hidden method, which is now just a stub method"
2917                 + " that does nothing.  Leave comments in b.android.com/114740982 if your "
2918                 + " application still depends on the previous behavior of this method.");
2919     }
2920 
2921     /**
2922      * Returns a map of all shortcut input method info and their subtypes.
2923      */
getShortcutInputMethodsAndSubtypes()2924     public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
2925         final List<InputMethodInfo> enabledImes = getEnabledInputMethodList();
2926 
2927         // Ensure we check system IMEs first.
2928         enabledImes.sort(Comparator.comparingInt(imi -> imi.isSystem() ? 0 : 1));
2929 
2930         final int numEnabledImes = enabledImes.size();
2931         for (int imiIndex = 0; imiIndex < numEnabledImes; ++imiIndex) {
2932             final InputMethodInfo imi = enabledImes.get(imiIndex);
2933             final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(
2934                     imi, true);
2935             final int subtypeCount = subtypes.size();
2936             for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) {
2937                 final InputMethodSubtype subtype = imi.getSubtypeAt(subtypeIndex);
2938                 if (SUBTYPE_MODE_VOICE.equals(subtype.getMode())) {
2939                     return Collections.singletonMap(imi, Collections.singletonList(subtype));
2940                 }
2941             }
2942         }
2943         return Collections.emptyMap();
2944     }
2945 
2946     /**
2947      * This is kept due to {@link android.compat.annotation.UnsupportedAppUsage}.
2948      *
2949      * <p>TODO(Bug 113914148): Check if we can remove this.  We have accidentally exposed
2950      * WindowManagerInternal#getInputMethodWindowVisibleHeight to app developers and some of them
2951      * started relying on it.</p>
2952      *
2953      * @return Something that is not well-defined.
2954      * @hide
2955      */
2956     @UnsupportedAppUsage
getInputMethodWindowVisibleHeight()2957     public int getInputMethodWindowVisibleHeight() {
2958         try {
2959             return mService.getInputMethodWindowVisibleHeight();
2960         } catch (RemoteException e) {
2961             throw e.rethrowFromSystemServer();
2962         }
2963     }
2964 
2965     /**
2966      * An internal API for {@link android.app.ActivityView} to report where its embedded virtual
2967      * display is placed.
2968      *
2969      * @param childDisplayId Display ID of the embedded virtual display.
2970      * @param matrix {@link Matrix} to convert virtual display screen coordinates to
2971      *               the host screen coordinates. {@code null} to clear the relationship.
2972      * @hide
2973      */
reportActivityView(int childDisplayId, @Nullable Matrix matrix)2974     public void reportActivityView(int childDisplayId, @Nullable Matrix matrix) {
2975         try {
2976             final float[] matrixValues;
2977             if (matrix == null) {
2978                 matrixValues = null;
2979             } else {
2980                 matrixValues = new float[9];
2981                 matrix.getValues(matrixValues);
2982             }
2983             mService.reportActivityView(mClient, childDisplayId, matrixValues);
2984         } catch (RemoteException e) {
2985             throw e.rethrowFromSystemServer();
2986         }
2987     }
2988 
2989     /**
2990      * Force switch to the last used input method and subtype. If the last input method didn't have
2991      * any subtypes, the framework will simply switch to the last input method with no subtype
2992      * specified.
2993      * @param imeToken Supplies the identifying token given to an input method when it was started,
2994      * which allows it to perform this operation on itself.
2995      * @return true if the current input method and subtype was successfully switched to the last
2996      * used input method and subtype.
2997      * @deprecated Use {@link InputMethodService#switchToPreviousInputMethod()} instead. This method
2998      * was intended for IME developers who should be accessing APIs through the service. APIs in
2999      * this class are intended for app developers interacting with the IME.
3000      */
3001     @Deprecated
switchToLastInputMethod(IBinder imeToken)3002     public boolean switchToLastInputMethod(IBinder imeToken) {
3003         return InputMethodPrivilegedOperationsRegistry.get(imeToken).switchToPreviousInputMethod();
3004     }
3005 
3006     /**
3007      * Force switch to the next input method and subtype. If there is no IME enabled except
3008      * current IME and subtype, do nothing.
3009      * @param imeToken Supplies the identifying token given to an input method when it was started,
3010      * which allows it to perform this operation on itself.
3011      * @param onlyCurrentIme if true, the framework will find the next subtype which
3012      * belongs to the current IME
3013      * @return true if the current input method and subtype was successfully switched to the next
3014      * input method and subtype.
3015      * @deprecated Use {@link InputMethodService#switchToNextInputMethod(boolean)} instead. This
3016      * method was intended for IME developers who should be accessing APIs through the service.
3017      * APIs in this class are intended for app developers interacting with the IME.
3018      */
3019     @Deprecated
switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme)3020     public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
3021         return InputMethodPrivilegedOperationsRegistry.get(imeToken)
3022                 .switchToNextInputMethod(onlyCurrentIme);
3023     }
3024 
3025     /**
3026      * Returns true if the current IME needs to offer the users ways to switch to a next input
3027      * method (e.g. a globe key.).
3028      * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
3029      * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
3030      * <p> Note that the system determines the most appropriate next input method
3031      * and subtype in order to provide the consistent user experience in switching
3032      * between IMEs and subtypes.
3033      * @param imeToken Supplies the identifying token given to an input method when it was started,
3034      * which allows it to perform this operation on itself.
3035      * @deprecated Use {@link InputMethodService#shouldOfferSwitchingToNextInputMethod()}
3036      * instead. This method was intended for IME developers who should be accessing APIs through
3037      * the service. APIs in this class are intended for app developers interacting with the IME.
3038      */
3039     @Deprecated
shouldOfferSwitchingToNextInputMethod(IBinder imeToken)3040     public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
3041         return InputMethodPrivilegedOperationsRegistry.get(imeToken)
3042                 .shouldOfferSwitchingToNextInputMethod();
3043     }
3044 
3045     /**
3046      * Set additional input method subtypes. Only a process which shares the same uid with the IME
3047      * can add additional input method subtypes to the IME.
3048      * Please note that a subtype's status is stored in the system.
3049      * For example, enabled subtypes are remembered by the framework even after they are removed
3050      * by using this method. If you re-add the same subtypes again,
3051      * they will just get enabled. If you want to avoid such conflicts, for instance, you may
3052      * want to create a "different" new subtype even with the same locale and mode,
3053      * by changing its extra value. The different subtype won't get affected by the stored past
3054      * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
3055      * to the current implementation.)
3056      *
3057      * <p>NOTE: If the same subtype exists in both the manifest XML file and additional subtypes
3058      * specified by {@code subtypes}, those multiple instances are automatically merged into one
3059      * instance.</p>
3060      *
3061      * <p>CAVEAT: In API Level 23 and prior, the system may do nothing if an empty
3062      * {@link InputMethodSubtype} is specified in {@code subtypes}, which prevents you from removing
3063      * the last one entry of additional subtypes. If your IME statically defines one or more
3064      * subtypes in the manifest XML file, you may be able to work around this limitation by
3065      * specifying one of those statically defined subtypes in {@code subtypes}.</p>
3066      *
3067      * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
3068      * @param subtypes subtypes will be added as additional subtypes of the current input method.
3069      * @deprecated For IMEs that have already implemented features like customizable/downloadable
3070      *             keyboard layouts/languages, please start migration to other approaches. One idea
3071      *             would be exposing only one unified {@link InputMethodSubtype} then implement
3072      *             IME's own language switching mechanism within that unified subtype. The support
3073      *             of "Additional Subtype" may be completely dropped in a future version of Android.
3074      */
3075     @Deprecated
setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes)3076     public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
3077         try {
3078             mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
3079         } catch (RemoteException e) {
3080             throw e.rethrowFromSystemServer();
3081         }
3082     }
3083 
getLastInputMethodSubtype()3084     public InputMethodSubtype getLastInputMethodSubtype() {
3085         try {
3086             return mService.getLastInputMethodSubtype();
3087         } catch (RemoteException e) {
3088             throw e.rethrowFromSystemServer();
3089         }
3090     }
3091 
maybeCallServedViewChangedLocked(EditorInfo tba)3092     private void maybeCallServedViewChangedLocked(EditorInfo tba) {
3093         if (mImeInsetsConsumer != null) {
3094             mImeInsetsConsumer.onServedEditorChanged(tba);
3095         }
3096     }
3097 
3098     /**
3099      * <p>This is used for CTS test only. Do not use this method outside of CTS package.<p/>
3100      * @return the ID of this display which this {@link InputMethodManager} resides
3101      * @hide
3102      */
3103     @TestApi
getDisplayId()3104     public int getDisplayId() {
3105         return mDisplayId;
3106     }
3107 
doDump(FileDescriptor fd, PrintWriter fout, String[] args)3108     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
3109         final Printer p = new PrintWriterPrinter(fout);
3110         p.println("Input method client state for " + this + ":");
3111 
3112         p.println("  mService=" + mService);
3113         p.println("  mMainLooper=" + mMainLooper);
3114         p.println("  mIInputContext=" + mIInputContext);
3115         p.println("  mActive=" + mActive
3116                 + " mRestartOnNextWindowFocus=" + mRestartOnNextWindowFocus
3117                 + " mBindSequence=" + mBindSequence
3118                 + " mCurId=" + mCurId);
3119         p.println("  mFullscreenMode=" + mFullscreenMode);
3120         p.println("  mCurMethod=" + mCurMethod);
3121         p.println("  mCurRootView=" + mCurRootView);
3122         p.println("  mServedView=" + getServedViewLocked());
3123         p.println("  mNextServedView=" + getNextServedViewLocked());
3124         p.println("  mServedConnecting=" + mServedConnecting);
3125         if (mCurrentTextBoxAttribute != null) {
3126             p.println("  mCurrentTextBoxAttribute:");
3127             mCurrentTextBoxAttribute.dump(p, "    ");
3128         } else {
3129             p.println("  mCurrentTextBoxAttribute: null");
3130         }
3131         p.println("  mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
3132         p.println("  mCompletions=" + Arrays.toString(mCompletions));
3133         p.println("  mCursorRect=" + mCursorRect);
3134         p.println("  mCursorSelStart=" + mCursorSelStart
3135                 + " mCursorSelEnd=" + mCursorSelEnd
3136                 + " mCursorCandStart=" + mCursorCandStart
3137                 + " mCursorCandEnd=" + mCursorCandEnd);
3138     }
3139 
3140     /**
3141      * Callback that is invoked when an input event that was dispatched to
3142      * the IME has been finished.
3143      * @hide
3144      */
3145     public interface FinishedInputEventCallback {
onFinishedInputEvent(Object token, boolean handled)3146         public void onFinishedInputEvent(Object token, boolean handled);
3147     }
3148 
3149     private final class ImeInputEventSender extends InputEventSender {
ImeInputEventSender(InputChannel inputChannel, Looper looper)3150         public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
3151             super(inputChannel, looper);
3152         }
3153 
3154         @Override
onInputEventFinished(int seq, boolean handled)3155         public void onInputEventFinished(int seq, boolean handled) {
3156             finishedInputEvent(seq, handled, false);
3157         }
3158     }
3159 
3160     private final class PendingEvent implements Runnable {
3161         public InputEvent mEvent;
3162         public Object mToken;
3163         public String mInputMethodId;
3164         public FinishedInputEventCallback mCallback;
3165         public Handler mHandler;
3166         public boolean mHandled;
3167 
recycle()3168         public void recycle() {
3169             mEvent = null;
3170             mToken = null;
3171             mInputMethodId = null;
3172             mCallback = null;
3173             mHandler = null;
3174             mHandled = false;
3175         }
3176 
3177         @Override
run()3178         public void run() {
3179             mCallback.onFinishedInputEvent(mToken, mHandled);
3180 
3181             synchronized (mH) {
3182                 recyclePendingEventLocked(this);
3183             }
3184         }
3185     }
3186 
dumpViewInfo(@ullable final View view)3187     private static String dumpViewInfo(@Nullable final View view) {
3188         if (view == null) {
3189             return "null";
3190         }
3191         final StringBuilder sb = new StringBuilder();
3192         sb.append(view);
3193         sb.append(",focus=" + view.hasFocus());
3194         sb.append(",windowFocus=" + view.hasWindowFocus());
3195         sb.append(",autofillUiShowing=" + isAutofillUIShowing(view));
3196         sb.append(",window=" + view.getWindowToken());
3197         sb.append(",displayId=" + view.getContext().getDisplayId());
3198         sb.append(",temporaryDetach=" + view.isTemporarilyDetached());
3199         sb.append(",hasImeFocus=" + view.hasImeFocus());
3200 
3201         return sb.toString();
3202     }
3203 }
3204