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