Home | History | Annotate | Download | only in inputmethod
      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 com.android.internal.os.SomeArgs;
     20 import com.android.internal.view.IInputConnectionWrapper;
     21 import com.android.internal.view.IInputContext;
     22 import com.android.internal.view.IInputMethodClient;
     23 import com.android.internal.view.IInputMethodManager;
     24 import com.android.internal.view.IInputMethodSession;
     25 import com.android.internal.view.InputBindResult;
     26 
     27 import android.content.Context;
     28 import android.graphics.Matrix;
     29 import android.graphics.Rect;
     30 import android.graphics.RectF;
     31 import android.os.Bundle;
     32 import android.os.Handler;
     33 import android.os.IBinder;
     34 import android.os.Looper;
     35 import android.os.Message;
     36 import android.os.RemoteException;
     37 import android.os.ResultReceiver;
     38 import android.os.ServiceManager;
     39 import android.os.Trace;
     40 import android.text.style.SuggestionSpan;
     41 import android.util.Log;
     42 import android.util.Pools.Pool;
     43 import android.util.Pools.SimplePool;
     44 import android.util.PrintWriterPrinter;
     45 import android.util.Printer;
     46 import android.util.SparseArray;
     47 import android.view.InputChannel;
     48 import android.view.InputEvent;
     49 import android.view.InputEventSender;
     50 import android.view.KeyEvent;
     51 import android.view.View;
     52 import android.view.ViewRootImpl;
     53 
     54 import java.io.FileDescriptor;
     55 import java.io.PrintWriter;
     56 import java.util.ArrayList;
     57 import java.util.HashMap;
     58 import java.util.List;
     59 import java.util.Map;
     60 import java.util.Objects;
     61 import java.util.concurrent.CountDownLatch;
     62 import java.util.concurrent.TimeUnit;
     63 
     64 /**
     65  * Central system API to the overall input method framework (IMF) architecture,
     66  * which arbitrates interaction between applications and the current input method.
     67  * You can retrieve an instance of this interface with
     68  * {@link Context#getSystemService(String) Context.getSystemService()}.
     69  *
     70  * <p>Topics covered here:
     71  * <ol>
     72  * <li><a href="#ArchitectureOverview">Architecture Overview</a>
     73  * <li><a href="#Applications">Applications</a>
     74  * <li><a href="#InputMethods">Input Methods</a>
     75  * <li><a href="#Security">Security</a>
     76  * </ol>
     77  *
     78  * <a name="ArchitectureOverview"></a>
     79  * <h3>Architecture Overview</h3>
     80  *
     81  * <p>There are three primary parties involved in the input method
     82  * framework (IMF) architecture:</p>
     83  *
     84  * <ul>
     85  * <li> The <strong>input method manager</strong> as expressed by this class
     86  * is the central point of the system that manages interaction between all
     87  * other parts.  It is expressed as the client-side API here which exists
     88  * in each application context and communicates with a global system service
     89  * that manages the interaction across all processes.
     90  * <li> An <strong>input method (IME)</strong> implements a particular
     91  * interaction model allowing the user to generate text.  The system binds
     92  * to the current input method that is use, causing it to be created and run,
     93  * and tells it when to hide and show its UI.  Only one IME is running at a time.
     94  * <li> Multiple <strong>client applications</strong> arbitrate with the input
     95  * method manager for input focus and control over the state of the IME.  Only
     96  * one such client is ever active (working with the IME) at a time.
     97  * </ul>
     98  *
     99  *
    100  * <a name="Applications"></a>
    101  * <h3>Applications</h3>
    102  *
    103  * <p>In most cases, applications that are using the standard
    104  * {@link android.widget.TextView} or its subclasses will have little they need
    105  * to do to work well with soft input methods.  The main things you need to
    106  * be aware of are:</p>
    107  *
    108  * <ul>
    109  * <li> Properly set the {@link android.R.attr#inputType} in your editable
    110  * text views, so that the input method will have enough context to help the
    111  * user in entering text into them.
    112  * <li> Deal well with losing screen space when the input method is
    113  * displayed.  Ideally an application should handle its window being resized
    114  * smaller, but it can rely on the system performing panning of the window
    115  * if needed.  You should set the {@link android.R.attr#windowSoftInputMode}
    116  * attribute on your activity or the corresponding values on windows you
    117  * create to help the system determine whether to pan or resize (it will
    118  * try to determine this automatically but may get it wrong).
    119  * <li> You can also control the preferred soft input state (open, closed, etc)
    120  * for your window using the same {@link android.R.attr#windowSoftInputMode}
    121  * attribute.
    122  * </ul>
    123  *
    124  * <p>More finer-grained control is available through the APIs here to directly
    125  * interact with the IMF and its IME -- either showing or hiding the input
    126  * area, letting the user pick an input method, etc.</p>
    127  *
    128  * <p>For the rare people amongst us writing their own text editors, you
    129  * will need to implement {@link android.view.View#onCreateInputConnection}
    130  * to return a new instance of your own {@link InputConnection} interface
    131  * allowing the IME to interact with your editor.</p>
    132  *
    133  *
    134  * <a name="InputMethods"></a>
    135  * <h3>Input Methods</h3>
    136  *
    137  * <p>An input method (IME) is implemented
    138  * as a {@link android.app.Service}, typically deriving from
    139  * {@link android.inputmethodservice.InputMethodService}.  It must provide
    140  * the core {@link InputMethod} interface, though this is normally handled by
    141  * {@link android.inputmethodservice.InputMethodService} and implementors will
    142  * only need to deal with the higher-level API there.</p>
    143  *
    144  * See the {@link android.inputmethodservice.InputMethodService} class for
    145  * more information on implementing IMEs.
    146  *
    147  *
    148  * <a name="Security"></a>
    149  * <h3>Security</h3>
    150  *
    151  * <p>There are a lot of security issues associated with input methods,
    152  * since they essentially have freedom to completely drive the UI and monitor
    153  * everything the user enters.  The Android input method framework also allows
    154  * arbitrary third party IMEs, so care must be taken to restrict their
    155  * selection and interactions.</p>
    156  *
    157  * <p>Here are some key points about the security architecture behind the
    158  * IMF:</p>
    159  *
    160  * <ul>
    161  * <li> <p>Only the system is allowed to directly access an IME's
    162  * {@link InputMethod} interface, via the
    163  * {@link android.Manifest.permission#BIND_INPUT_METHOD} permission.  This is
    164  * enforced in the system by not binding to an input method service that does
    165  * not require this permission, so the system can guarantee no other untrusted
    166  * clients are accessing the current input method outside of its control.</p>
    167  *
    168  * <li> <p>There may be many client processes of the IMF, but only one may
    169  * be active at a time.  The inactive clients can not interact with key
    170  * parts of the IMF through the mechanisms described below.</p>
    171  *
    172  * <li> <p>Clients of an input method are only given access to its
    173  * {@link InputMethodSession} interface.  One instance of this interface is
    174  * created for each client, and only calls from the session associated with
    175  * the active client will be processed by the current IME.  This is enforced
    176  * by {@link android.inputmethodservice.AbstractInputMethodService} for normal
    177  * IMEs, but must be explicitly handled by an IME that is customizing the
    178  * raw {@link InputMethodSession} implementation.</p>
    179  *
    180  * <li> <p>Only the active client's {@link InputConnection} will accept
    181  * operations.  The IMF tells each client process whether it is active, and
    182  * the framework enforces that in inactive processes calls on to the current
    183  * InputConnection will be ignored.  This ensures that the current IME can
    184  * only deliver events and text edits to the UI that the user sees as
    185  * being in focus.</p>
    186  *
    187  * <li> <p>An IME can never interact with an {@link InputConnection} while
    188  * the screen is off.  This is enforced by making all clients inactive while
    189  * the screen is off, and prevents bad IMEs from driving the UI when the user
    190  * can not be aware of its behavior.</p>
    191  *
    192  * <li> <p>A client application can ask that the system let the user pick a
    193  * new IME, but can not programmatically switch to one itself.  This avoids
    194  * malicious applications from switching the user to their own IME, which
    195  * remains running when the user navigates away to another application.  An
    196  * IME, on the other hand, <em>is</em> allowed to programmatically switch
    197  * the system to another IME, since it already has full control of user
    198  * input.</p>
    199  *
    200  * <li> <p>The user must explicitly enable a new IME in settings before
    201  * they can switch to it, to confirm with the system that they know about it
    202  * and want to make it available for use.</p>
    203  * </ul>
    204  */
    205 public final class InputMethodManager {
    206     static final boolean DEBUG = false;
    207     static final String TAG = "InputMethodManager";
    208 
    209     static final String PENDING_EVENT_COUNTER = "aq:imm";
    210 
    211     static InputMethodManager sInstance;
    212 
    213     /**
    214      * @hide Flag for IInputMethodManager.windowGainedFocus: a view in
    215      * the window has input focus.
    216      */
    217     public static final int CONTROL_WINDOW_VIEW_HAS_FOCUS = 1<<0;
    218 
    219     /**
    220      * @hide Flag for IInputMethodManager.windowGainedFocus: the focus
    221      * is a text editor.
    222      */
    223     public static final int CONTROL_WINDOW_IS_TEXT_EDITOR = 1<<1;
    224 
    225     /**
    226      * @hide Flag for IInputMethodManager.windowGainedFocus: this is the first
    227      * time the window has gotten focus.
    228      */
    229     public static final int CONTROL_WINDOW_FIRST = 1<<2;
    230 
    231     /**
    232      * @hide Flag for IInputMethodManager.startInput: this is the first
    233      * time the window has gotten focus.
    234      */
    235     public static final int CONTROL_START_INITIAL = 1<<8;
    236 
    237     /**
    238      * Timeout in milliseconds for delivering a key to an IME.
    239      */
    240     static final long INPUT_METHOD_NOT_RESPONDING_TIMEOUT = 2500;
    241 
    242     /** @hide */
    243     public static final int DISPATCH_IN_PROGRESS = -1;
    244 
    245     /** @hide */
    246     public static final int DISPATCH_NOT_HANDLED = 0;
    247 
    248     /** @hide */
    249     public static final int DISPATCH_HANDLED = 1;
    250 
    251     final IInputMethodManager mService;
    252     final Looper mMainLooper;
    253 
    254     // For scheduling work on the main thread.  This also serves as our
    255     // global lock.
    256     final H mH;
    257 
    258     // Our generic input connection if the current target does not have its own.
    259     final IInputContext mIInputContext;
    260 
    261     /**
    262      * True if this input method client is active, initially false.
    263      */
    264     boolean mActive = false;
    265 
    266     /**
    267      * Set whenever this client becomes inactive, to know we need to reset
    268      * state with the IME the next time we receive focus.
    269      */
    270     boolean mHasBeenInactive = true;
    271 
    272     /**
    273      * As reported by IME through InputConnection.
    274      */
    275     boolean mFullscreenMode;
    276 
    277     // -----------------------------------------------------------
    278 
    279     /**
    280      * This is the root view of the overall window that currently has input
    281      * method focus.
    282      */
    283     View mCurRootView;
    284     /**
    285      * This is the view that should currently be served by an input method,
    286      * regardless of the state of setting that up.
    287      */
    288     View mServedView;
    289     /**
    290      * This is then next view that will be served by the input method, when
    291      * we get around to updating things.
    292      */
    293     View mNextServedView;
    294     /**
    295      * This is set when we are in the process of connecting, to determine
    296      * when we have actually finished.
    297      */
    298     boolean mServedConnecting;
    299     /**
    300      * This is non-null when we have connected the served view; it holds
    301      * the attributes that were last retrieved from the served view and given
    302      * to the input connection.
    303      */
    304     EditorInfo mCurrentTextBoxAttribute;
    305     /**
    306      * The InputConnection that was last retrieved from the served view.
    307      */
    308     InputConnection mServedInputConnection;
    309     ControlledInputConnectionWrapper mServedInputConnectionWrapper;
    310     /**
    311      * The completions that were last provided by the served view.
    312      */
    313     CompletionInfo[] mCompletions;
    314 
    315     // Cursor position on the screen.
    316     Rect mTmpCursorRect = new Rect();
    317     Rect mCursorRect = new Rect();
    318     int mCursorSelStart;
    319     int mCursorSelEnd;
    320     int mCursorCandStart;
    321     int mCursorCandEnd;
    322 
    323     /**
    324      * Represents an invalid action notification sequence number. {@link InputMethodManagerService}
    325      * always issues a positive integer for action notification sequence numbers. Thus -1 is
    326      * guaranteed to be different from any valid sequence number.
    327      */
    328     private static final int NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER = -1;
    329     /**
    330      * The next sequence number that is to be sent to {@link InputMethodManagerService} via
    331      * {@link IInputMethodManager#notifyUserAction(int)} at once when a user action is observed.
    332      */
    333     private int mNextUserActionNotificationSequenceNumber =
    334             NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;
    335 
    336     /**
    337      * The last sequence number that is already sent to {@link InputMethodManagerService}.
    338      */
    339     private int mLastSentUserActionNotificationSequenceNumber =
    340             NOT_AN_ACTION_NOTIFICATION_SEQUENCE_NUMBER;
    341 
    342     /**
    343      * The instance that has previously been sent to the input method.
    344      */
    345     private CursorAnchorInfo mCursorAnchorInfo = null;
    346 
    347     /**
    348      * The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
    349      */
    350     private final int[] mViewTopLeft = new int[2];
    351 
    352     /**
    353      * The matrix to convert the view location into screen coordinates in {@link #updateCursor}.
    354      */
    355     private final Matrix mViewToScreenMatrix = new Matrix();
    356 
    357     // -----------------------------------------------------------
    358 
    359     /**
    360      * Sequence number of this binding, as returned by the server.
    361      */
    362     int mBindSequence = -1;
    363     /**
    364      * ID of the method we are bound to.
    365      */
    366     String mCurId;
    367     /**
    368      * The actual instance of the method to make calls on it.
    369      */
    370     IInputMethodSession mCurMethod;
    371     InputChannel mCurChannel;
    372     ImeInputEventSender mCurSender;
    373 
    374     private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0;
    375 
    376     /**
    377      * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
    378      */
    379     private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
    380 
    381     final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
    382     final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
    383 
    384     // -----------------------------------------------------------
    385 
    386     static final int MSG_DUMP = 1;
    387     static final int MSG_BIND = 2;
    388     static final int MSG_UNBIND = 3;
    389     static final int MSG_SET_ACTIVE = 4;
    390     static final int MSG_SEND_INPUT_EVENT = 5;
    391     static final int MSG_TIMEOUT_INPUT_EVENT = 6;
    392     static final int MSG_FLUSH_INPUT_EVENT = 7;
    393     static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9;
    394 
    395     class H extends Handler {
    396         H(Looper looper) {
    397             super(looper, null, true);
    398         }
    399 
    400         @Override
    401         public void handleMessage(Message msg) {
    402             switch (msg.what) {
    403                 case MSG_DUMP: {
    404                     SomeArgs args = (SomeArgs)msg.obj;
    405                     try {
    406                         doDump((FileDescriptor)args.arg1,
    407                                 (PrintWriter)args.arg2, (String[])args.arg3);
    408                     } catch (RuntimeException e) {
    409                         ((PrintWriter)args.arg2).println("Exception: " + e);
    410                     }
    411                     synchronized (args.arg4) {
    412                         ((CountDownLatch)args.arg4).countDown();
    413                     }
    414                     args.recycle();
    415                     return;
    416                 }
    417                 case MSG_BIND: {
    418                     final InputBindResult res = (InputBindResult)msg.obj;
    419                     if (DEBUG) {
    420                         Log.i(TAG, "handleMessage: MSG_BIND " + res.sequence + "," + res.id);
    421                     }
    422                     synchronized (mH) {
    423                         if (mBindSequence < 0 || mBindSequence != res.sequence) {
    424                             Log.w(TAG, "Ignoring onBind: cur seq=" + mBindSequence
    425                                     + ", given seq=" + res.sequence);
    426                             if (res.channel != null && res.channel != mCurChannel) {
    427                                 res.channel.dispose();
    428                             }
    429                             return;
    430                         }
    431 
    432                         mRequestUpdateCursorAnchorInfoMonitorMode =
    433                                 REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE;
    434 
    435                         setInputChannelLocked(res.channel);
    436                         mCurMethod = res.method;
    437                         mCurId = res.id;
    438                         mBindSequence = res.sequence;
    439                     }
    440                     startInputInner(null, 0, 0, 0);
    441                     return;
    442                 }
    443                 case MSG_UNBIND: {
    444                     final int sequence = msg.arg1;
    445                     if (DEBUG) {
    446                         Log.i(TAG, "handleMessage: MSG_UNBIND " + sequence);
    447                     }
    448                     boolean startInput = false;
    449                     synchronized (mH) {
    450                         if (mBindSequence == sequence) {
    451                             if (false) {
    452                                 // XXX the server has already unbound!
    453                                 if (mCurMethod != null && mCurrentTextBoxAttribute != null) {
    454                                     try {
    455                                         mCurMethod.finishInput();
    456                                     } catch (RemoteException e) {
    457                                         Log.w(TAG, "IME died: " + mCurId, e);
    458                                     }
    459                                 }
    460                             }
    461                             clearBindingLocked();
    462 
    463                             // If we were actively using the last input method, then
    464                             // we would like to re-connect to the next input method.
    465                             if (mServedView != null && mServedView.isFocused()) {
    466                                 mServedConnecting = true;
    467                             }
    468                             if (mActive) {
    469                                 startInput = true;
    470                             }
    471                         }
    472                     }
    473                     if (startInput) {
    474                         startInputInner(null, 0, 0, 0);
    475                     }
    476                     return;
    477                 }
    478                 case MSG_SET_ACTIVE: {
    479                     final boolean active = msg.arg1 != 0;
    480                     if (DEBUG) {
    481                         Log.i(TAG, "handleMessage: MSG_SET_ACTIVE " + active + ", was " + mActive);
    482                     }
    483                     synchronized (mH) {
    484                         mActive = active;
    485                         mFullscreenMode = false;
    486                         if (!active) {
    487                             // Some other client has starting using the IME, so note
    488                             // that this happened and make sure our own editor's
    489                             // state is reset.
    490                             mHasBeenInactive = true;
    491                             try {
    492                                 // Note that finishComposingText() is allowed to run
    493                                 // even when we are not active.
    494                                 mIInputContext.finishComposingText();
    495                             } catch (RemoteException e) {
    496                             }
    497                             // Check focus again in case that "onWindowFocus" is called before
    498                             // handling this message.
    499                             if (mServedView != null && mServedView.hasWindowFocus()) {
    500                                 // "finishComposingText" has been already called above. So we
    501                                 // should not call mServedInputConnection.finishComposingText here.
    502                                 // Also, please note that this handler thread could be different
    503                                 // from a thread that created mServedView. That could happen
    504                                 // the current activity is running in the system process.
    505                                 // In that case, we really should not call
    506                                 // mServedInputConnection.finishComposingText.
    507                                 if (checkFocusNoStartInput(mHasBeenInactive, false)) {
    508                                     startInputInner(null, 0, 0, 0);
    509                                 }
    510                             }
    511                         }
    512                     }
    513                     return;
    514                 }
    515                 case MSG_SEND_INPUT_EVENT: {
    516                     sendInputEventAndReportResultOnMainLooper((PendingEvent)msg.obj);
    517                     return;
    518                 }
    519                 case MSG_TIMEOUT_INPUT_EVENT: {
    520                     finishedInputEvent(msg.arg1, false, true);
    521                     return;
    522                 }
    523                 case MSG_FLUSH_INPUT_EVENT: {
    524                     finishedInputEvent(msg.arg1, false, false);
    525                     return;
    526                 }
    527                 case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
    528                     synchronized (mH) {
    529                         mNextUserActionNotificationSequenceNumber = msg.arg1;
    530                     }
    531                 }
    532             }
    533         }
    534     }
    535 
    536     private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
    537         private final InputMethodManager mParentInputMethodManager;
    538         private boolean mActive;
    539 
    540         public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
    541                 final InputMethodManager inputMethodManager) {
    542             super(mainLooper, conn);
    543             mParentInputMethodManager = inputMethodManager;
    544             mActive = true;
    545         }
    546 
    547         @Override
    548         public boolean isActive() {
    549             return mParentInputMethodManager.mActive && mActive;
    550         }
    551 
    552         void deactivate() {
    553             mActive = false;
    554         }
    555     }
    556 
    557     final IInputMethodClient.Stub mClient = new IInputMethodClient.Stub() {
    558         @Override
    559         protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
    560             // No need to check for dump permission, since we only give this
    561             // interface to the system.
    562             CountDownLatch latch = new CountDownLatch(1);
    563             SomeArgs sargs = SomeArgs.obtain();
    564             sargs.arg1 = fd;
    565             sargs.arg2 = fout;
    566             sargs.arg3 = args;
    567             sargs.arg4 = latch;
    568             mH.sendMessage(mH.obtainMessage(MSG_DUMP, sargs));
    569             try {
    570                 if (!latch.await(5, TimeUnit.SECONDS)) {
    571                     fout.println("Timeout waiting for dump");
    572                 }
    573             } catch (InterruptedException e) {
    574                 fout.println("Interrupted waiting for dump");
    575             }
    576         }
    577 
    578         @Override
    579         public void setUsingInputMethod(boolean state) {
    580         }
    581 
    582         @Override
    583         public void onBindMethod(InputBindResult res) {
    584             mH.sendMessage(mH.obtainMessage(MSG_BIND, res));
    585         }
    586 
    587         @Override
    588         public void onUnbindMethod(int sequence) {
    589             mH.sendMessage(mH.obtainMessage(MSG_UNBIND, sequence, 0));
    590         }
    591 
    592         @Override
    593         public void setActive(boolean active) {
    594             mH.sendMessage(mH.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, 0));
    595         }
    596 
    597         @Override
    598         public void setUserActionNotificationSequenceNumber(int sequenceNumber) {
    599             mH.sendMessage(mH.obtainMessage(MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
    600                     sequenceNumber, 0));
    601         }
    602     };
    603 
    604     final InputConnection mDummyInputConnection = new BaseInputConnection(this, false);
    605 
    606     InputMethodManager(IInputMethodManager service, Looper looper) {
    607         mService = service;
    608         mMainLooper = looper;
    609         mH = new H(looper);
    610         mIInputContext = new ControlledInputConnectionWrapper(looper,
    611                 mDummyInputConnection, this);
    612     }
    613 
    614     /**
    615      * Retrieve the global InputMethodManager instance, creating it if it
    616      * doesn't already exist.
    617      * @hide
    618      */
    619     public static InputMethodManager getInstance() {
    620         synchronized (InputMethodManager.class) {
    621             if (sInstance == null) {
    622                 IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
    623                 IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
    624                 sInstance = new InputMethodManager(service, Looper.getMainLooper());
    625             }
    626             return sInstance;
    627         }
    628     }
    629 
    630     /**
    631      * Private optimization: retrieve the global InputMethodManager instance,
    632      * if it exists.
    633      * @hide
    634      */
    635     public static InputMethodManager peekInstance() {
    636         return sInstance;
    637     }
    638 
    639     /** @hide */
    640     public IInputMethodClient getClient() {
    641         return mClient;
    642     }
    643 
    644     /** @hide */
    645     public IInputContext getInputContext() {
    646         return mIInputContext;
    647     }
    648 
    649     public List<InputMethodInfo> getInputMethodList() {
    650         try {
    651             return mService.getInputMethodList();
    652         } catch (RemoteException e) {
    653             throw new RuntimeException(e);
    654         }
    655     }
    656 
    657     public List<InputMethodInfo> getEnabledInputMethodList() {
    658         try {
    659             return mService.getEnabledInputMethodList();
    660         } catch (RemoteException e) {
    661             throw new RuntimeException(e);
    662         }
    663     }
    664 
    665     /**
    666      * Returns a list of enabled input method subtypes for the specified input method info.
    667      * @param imi An input method info whose subtypes list will be returned.
    668      * @param allowsImplicitlySelectedSubtypes A boolean flag to allow to return the implicitly
    669      * selected subtypes. If an input method info doesn't have enabled subtypes, the framework
    670      * will implicitly enable subtypes according to the current system language.
    671      */
    672     public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(InputMethodInfo imi,
    673             boolean allowsImplicitlySelectedSubtypes) {
    674         try {
    675             return mService.getEnabledInputMethodSubtypeList(
    676                     imi == null ? null : imi.getId(), allowsImplicitlySelectedSubtypes);
    677         } catch (RemoteException e) {
    678             throw new RuntimeException(e);
    679         }
    680     }
    681 
    682     public void showStatusIcon(IBinder imeToken, String packageName, int iconId) {
    683         try {
    684             mService.updateStatusIcon(imeToken, packageName, iconId);
    685         } catch (RemoteException e) {
    686             throw new RuntimeException(e);
    687         }
    688     }
    689 
    690     public void hideStatusIcon(IBinder imeToken) {
    691         try {
    692             mService.updateStatusIcon(imeToken, null, 0);
    693         } catch (RemoteException e) {
    694             throw new RuntimeException(e);
    695         }
    696     }
    697 
    698     /** @hide */
    699     public void setImeWindowStatus(IBinder imeToken, int vis, int backDisposition) {
    700         try {
    701             mService.setImeWindowStatus(imeToken, vis, backDisposition);
    702         } catch (RemoteException e) {
    703             throw new RuntimeException(e);
    704         }
    705     }
    706 
    707     /** @hide */
    708     public void setFullscreenMode(boolean fullScreen) {
    709         mFullscreenMode = fullScreen;
    710     }
    711 
    712     /** @hide */
    713     public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
    714         try {
    715             mService.registerSuggestionSpansForNotification(spans);
    716         } catch (RemoteException e) {
    717             throw new RuntimeException(e);
    718         }
    719     }
    720 
    721     /** @hide */
    722     public void notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
    723         try {
    724             mService.notifySuggestionPicked(span, originalString, index);
    725         } catch (RemoteException e) {
    726             throw new RuntimeException(e);
    727         }
    728     }
    729 
    730     /**
    731      * Allows you to discover whether the attached input method is running
    732      * in fullscreen mode.  Return true if it is fullscreen, entirely covering
    733      * your UI, else returns false.
    734      */
    735     public boolean isFullscreenMode() {
    736         return mFullscreenMode;
    737     }
    738 
    739     /**
    740      * Return true if the given view is the currently active view for the
    741      * input method.
    742      */
    743     public boolean isActive(View view) {
    744         checkFocus();
    745         synchronized (mH) {
    746             return (mServedView == view
    747                     || (mServedView != null
    748                             && mServedView.checkInputConnectionProxy(view)))
    749                     && mCurrentTextBoxAttribute != null;
    750         }
    751     }
    752 
    753     /**
    754      * Return true if any view is currently active in the input method.
    755      */
    756     public boolean isActive() {
    757         checkFocus();
    758         synchronized (mH) {
    759             return mServedView != null && mCurrentTextBoxAttribute != null;
    760         }
    761     }
    762 
    763     /**
    764      * Return true if the currently served view is accepting full text edits.
    765      * If false, it has no input connection, so can only handle raw key events.
    766      */
    767     public boolean isAcceptingText() {
    768         checkFocus();
    769         return mServedInputConnection != null;
    770     }
    771 
    772     /**
    773      * Reset all of the state associated with being bound to an input method.
    774      */
    775     void clearBindingLocked() {
    776         if (DEBUG) Log.v(TAG, "Clearing binding!");
    777         clearConnectionLocked();
    778         setInputChannelLocked(null);
    779         mBindSequence = -1;
    780         mCurId = null;
    781         mCurMethod = null;
    782     }
    783 
    784     void setInputChannelLocked(InputChannel channel) {
    785         if (mCurChannel != channel) {
    786             if (mCurSender != null) {
    787                 flushPendingEventsLocked();
    788                 mCurSender.dispose();
    789                 mCurSender = null;
    790             }
    791             if (mCurChannel != null) {
    792                 mCurChannel.dispose();
    793             }
    794             mCurChannel = channel;
    795         }
    796     }
    797 
    798     /**
    799      * Reset all of the state associated with a served view being connected
    800      * to an input method
    801      */
    802     void clearConnectionLocked() {
    803         mCurrentTextBoxAttribute = null;
    804         mServedInputConnection = null;
    805         if (mServedInputConnectionWrapper != null) {
    806             mServedInputConnectionWrapper.deactivate();
    807             mServedInputConnectionWrapper = null;
    808         }
    809     }
    810 
    811     /**
    812      * Disconnect any existing input connection, clearing the served view.
    813      */
    814     void finishInputLocked() {
    815         mCurRootView = null;
    816         mNextServedView = null;
    817         if (mServedView != null) {
    818             if (DEBUG) Log.v(TAG, "FINISH INPUT: " + mServedView);
    819 
    820             if (mCurrentTextBoxAttribute != null) {
    821                 try {
    822                     mService.finishInput(mClient);
    823                 } catch (RemoteException e) {
    824                 }
    825             }
    826 
    827             notifyInputConnectionFinished();
    828 
    829             mServedView = null;
    830             mCompletions = null;
    831             mServedConnecting = false;
    832             clearConnectionLocked();
    833         }
    834     }
    835 
    836     /**
    837      * Notifies the served view that the current InputConnection will no longer be used.
    838      */
    839     private void notifyInputConnectionFinished() {
    840         if (mServedView != null && mServedInputConnection != null) {
    841             // We need to tell the previously served view that it is no
    842             // longer the input target, so it can reset its state.  Schedule
    843             // this call on its window's Handler so it will be on the correct
    844             // thread and outside of our lock.
    845             ViewRootImpl viewRootImpl = mServedView.getViewRootImpl();
    846             if (viewRootImpl != null) {
    847                 // This will result in a call to reportFinishInputConnection() below.
    848                 viewRootImpl.dispatchFinishInputConnection(mServedInputConnection);
    849             }
    850         }
    851     }
    852 
    853     /**
    854      * Called from the FINISH_INPUT_CONNECTION message above.
    855      * @hide
    856      */
    857     public void reportFinishInputConnection(InputConnection ic) {
    858         if (mServedInputConnection != ic) {
    859             ic.finishComposingText();
    860             // To avoid modifying the public InputConnection interface
    861             if (ic instanceof BaseInputConnection) {
    862                 ((BaseInputConnection) ic).reportFinish();
    863             }
    864         }
    865     }
    866 
    867     public void displayCompletions(View view, CompletionInfo[] completions) {
    868         checkFocus();
    869         synchronized (mH) {
    870             if (mServedView != view && (mServedView == null
    871                             || !mServedView.checkInputConnectionProxy(view))) {
    872                 return;
    873             }
    874 
    875             mCompletions = completions;
    876             if (mCurMethod != null) {
    877                 try {
    878                     mCurMethod.displayCompletions(mCompletions);
    879                 } catch (RemoteException e) {
    880                 }
    881             }
    882         }
    883     }
    884 
    885     public void updateExtractedText(View view, int token, ExtractedText text) {
    886         checkFocus();
    887         synchronized (mH) {
    888             if (mServedView != view && (mServedView == null
    889                     || !mServedView.checkInputConnectionProxy(view))) {
    890                 return;
    891             }
    892 
    893             if (mCurMethod != null) {
    894                 try {
    895                     mCurMethod.updateExtractedText(token, text);
    896                 } catch (RemoteException e) {
    897                 }
    898             }
    899         }
    900     }
    901 
    902     /**
    903      * Flag for {@link #showSoftInput} to indicate that this is an implicit
    904      * request to show the input window, not as the result of a direct request
    905      * by the user.  The window may not be shown in this case.
    906      */
    907     public static final int SHOW_IMPLICIT = 0x0001;
    908 
    909     /**
    910      * Flag for {@link #showSoftInput} to indicate that the user has forced
    911      * the input method open (such as by long-pressing menu) so it should
    912      * not be closed until they explicitly do so.
    913      */
    914     public static final int SHOW_FORCED = 0x0002;
    915 
    916     /**
    917      * Synonym for {@link #showSoftInput(View, int, ResultReceiver)} without
    918      * a result receiver: explicitly request that the current input method's
    919      * soft input area be shown to the user, if needed.
    920      *
    921      * @param view The currently focused view, which would like to receive
    922      * soft keyboard input.
    923      * @param flags Provides additional operating flags.  Currently may be
    924      * 0 or have the {@link #SHOW_IMPLICIT} bit set.
    925      */
    926     public boolean showSoftInput(View view, int flags) {
    927         return showSoftInput(view, flags, null);
    928     }
    929 
    930     /**
    931      * Flag for the {@link ResultReceiver} result code from
    932      * {@link #showSoftInput(View, int, ResultReceiver)} and
    933      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
    934      * state of the soft input window was unchanged and remains shown.
    935      */
    936     public static final int RESULT_UNCHANGED_SHOWN = 0;
    937 
    938     /**
    939      * Flag for the {@link ResultReceiver} result code from
    940      * {@link #showSoftInput(View, int, ResultReceiver)} and
    941      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
    942      * state of the soft input window was unchanged and remains hidden.
    943      */
    944     public static final int RESULT_UNCHANGED_HIDDEN = 1;
    945 
    946     /**
    947      * Flag for the {@link ResultReceiver} result code from
    948      * {@link #showSoftInput(View, int, ResultReceiver)} and
    949      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
    950      * state of the soft input window changed from hidden to shown.
    951      */
    952     public static final int RESULT_SHOWN = 2;
    953 
    954     /**
    955      * Flag for the {@link ResultReceiver} result code from
    956      * {@link #showSoftInput(View, int, ResultReceiver)} and
    957      * {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}: the
    958      * state of the soft input window changed from shown to hidden.
    959      */
    960     public static final int RESULT_HIDDEN = 3;
    961 
    962     /**
    963      * Explicitly request that the current input method's soft input area be
    964      * shown to the user, if needed.  Call this if the user interacts with
    965      * your view in such a way that they have expressed they would like to
    966      * start performing input into it.
    967      *
    968      * @param view The currently focused view, which would like to receive
    969      * soft keyboard input.
    970      * @param flags Provides additional operating flags.  Currently may be
    971      * 0 or have the {@link #SHOW_IMPLICIT} bit set.
    972      * @param resultReceiver If non-null, this will be called by the IME when
    973      * it has processed your request to tell you what it has done.  The result
    974      * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
    975      * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
    976      * {@link #RESULT_HIDDEN}.
    977      */
    978     public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
    979         checkFocus();
    980         synchronized (mH) {
    981             if (mServedView != view && (mServedView == null
    982                     || !mServedView.checkInputConnectionProxy(view))) {
    983                 return false;
    984             }
    985 
    986             try {
    987                 return mService.showSoftInput(mClient, flags, resultReceiver);
    988             } catch (RemoteException e) {
    989             }
    990 
    991             return false;
    992         }
    993     }
    994 
    995     /** @hide */
    996     public void showSoftInputUnchecked(int flags, ResultReceiver resultReceiver) {
    997         try {
    998             mService.showSoftInput(mClient, flags, resultReceiver);
    999         } catch (RemoteException e) {
   1000         }
   1001     }
   1002 
   1003     /**
   1004      * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft
   1005      * input window should only be hidden if it was not explicitly shown
   1006      * by the user.
   1007      */
   1008     public static final int HIDE_IMPLICIT_ONLY = 0x0001;
   1009 
   1010     /**
   1011      * Flag for {@link #hideSoftInputFromWindow} to indicate that the soft
   1012      * input window should normally be hidden, unless it was originally
   1013      * shown with {@link #SHOW_FORCED}.
   1014      */
   1015     public static final int HIDE_NOT_ALWAYS = 0x0002;
   1016 
   1017     /**
   1018      * Synonym for {@link #hideSoftInputFromWindow(IBinder, int, ResultReceiver)}
   1019      * without a result: request to hide the soft input window from the
   1020      * context of the window that is currently accepting input.
   1021      *
   1022      * @param windowToken The token of the window that is making the request,
   1023      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
   1024      * @param flags Provides additional operating flags.  Currently may be
   1025      * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
   1026      */
   1027     public boolean hideSoftInputFromWindow(IBinder windowToken, int flags) {
   1028         return hideSoftInputFromWindow(windowToken, flags, null);
   1029     }
   1030 
   1031     /**
   1032      * Request to hide the soft input window from the context of the window
   1033      * that is currently accepting input.  This should be called as a result
   1034      * of the user doing some actually than fairly explicitly requests to
   1035      * have the input window hidden.
   1036      *
   1037      * @param windowToken The token of the window that is making the request,
   1038      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
   1039      * @param flags Provides additional operating flags.  Currently may be
   1040      * 0 or have the {@link #HIDE_IMPLICIT_ONLY} bit set.
   1041      * @param resultReceiver If non-null, this will be called by the IME when
   1042      * it has processed your request to tell you what it has done.  The result
   1043      * code you receive may be either {@link #RESULT_UNCHANGED_SHOWN},
   1044      * {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
   1045      * {@link #RESULT_HIDDEN}.
   1046      */
   1047     public boolean hideSoftInputFromWindow(IBinder windowToken, int flags,
   1048             ResultReceiver resultReceiver) {
   1049         checkFocus();
   1050         synchronized (mH) {
   1051             if (mServedView == null || mServedView.getWindowToken() != windowToken) {
   1052                 return false;
   1053             }
   1054 
   1055             try {
   1056                 return mService.hideSoftInput(mClient, flags, resultReceiver);
   1057             } catch (RemoteException e) {
   1058             }
   1059             return false;
   1060         }
   1061     }
   1062 
   1063 
   1064     /**
   1065      * This method toggles the input method window display.
   1066      * If the input window is already displayed, it gets hidden.
   1067      * If not the input window will be displayed.
   1068      * @param windowToken The token of the window that is making the request,
   1069      * as returned by {@link View#getWindowToken() View.getWindowToken()}.
   1070      * @param showFlags Provides additional operating flags.  May be
   1071      * 0 or have the {@link #SHOW_IMPLICIT},
   1072      * {@link #SHOW_FORCED} bit set.
   1073      * @param hideFlags Provides additional operating flags.  May be
   1074      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
   1075      * {@link #HIDE_NOT_ALWAYS} bit set.
   1076      **/
   1077     public void toggleSoftInputFromWindow(IBinder windowToken, int showFlags, int hideFlags) {
   1078         synchronized (mH) {
   1079             if (mServedView == null || mServedView.getWindowToken() != windowToken) {
   1080                 return;
   1081             }
   1082             if (mCurMethod != null) {
   1083                 try {
   1084                     mCurMethod.toggleSoftInput(showFlags, hideFlags);
   1085                 } catch (RemoteException e) {
   1086                 }
   1087             }
   1088         }
   1089     }
   1090 
   1091     /*
   1092      * This method toggles the input method window display.
   1093      * If the input window is already displayed, it gets hidden.
   1094      * If not the input window will be displayed.
   1095      * @param showFlags Provides additional operating flags.  May be
   1096      * 0 or have the {@link #SHOW_IMPLICIT},
   1097      * {@link #SHOW_FORCED} bit set.
   1098      * @param hideFlags Provides additional operating flags.  May be
   1099      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
   1100      * {@link #HIDE_NOT_ALWAYS} bit set.
   1101      * @hide
   1102      */
   1103     public void toggleSoftInput(int showFlags, int hideFlags) {
   1104         if (mCurMethod != null) {
   1105             try {
   1106                 mCurMethod.toggleSoftInput(showFlags, hideFlags);
   1107             } catch (RemoteException e) {
   1108             }
   1109         }
   1110     }
   1111 
   1112     /**
   1113      * If the input method is currently connected to the given view,
   1114      * restart it with its new contents.  You should call this when the text
   1115      * within your view changes outside of the normal input method or key
   1116      * input flow, such as when an application calls TextView.setText().
   1117      *
   1118      * @param view The view whose text has changed.
   1119      */
   1120     public void restartInput(View view) {
   1121         checkFocus();
   1122         synchronized (mH) {
   1123             if (mServedView != view && (mServedView == null
   1124                     || !mServedView.checkInputConnectionProxy(view))) {
   1125                 return;
   1126             }
   1127 
   1128             mServedConnecting = true;
   1129         }
   1130 
   1131         startInputInner(null, 0, 0, 0);
   1132     }
   1133 
   1134     boolean startInputInner(IBinder windowGainingFocus, int controlFlags, int softInputMode,
   1135             int windowFlags) {
   1136         final View view;
   1137         synchronized (mH) {
   1138             view = mServedView;
   1139 
   1140             // Make sure we have a window token for the served view.
   1141             if (DEBUG) Log.v(TAG, "Starting input: view=" + view);
   1142             if (view == null) {
   1143                 if (DEBUG) Log.v(TAG, "ABORT input: no served view!");
   1144                 return false;
   1145             }
   1146         }
   1147 
   1148         // Now we need to get an input connection from the served view.
   1149         // This is complicated in a couple ways: we can't be holding our lock
   1150         // when calling out to the view, and we need to make sure we call into
   1151         // the view on the same thread that is driving its view hierarchy.
   1152         Handler vh = view.getHandler();
   1153         if (vh == null) {
   1154             // If the view doesn't have a handler, something has changed out
   1155             // from under us, so just close the current input.
   1156             // If we don't close the current input, the current input method can remain on the
   1157             // screen without a connection.
   1158             if (DEBUG) Log.v(TAG, "ABORT input: no handler for view! Close current input.");
   1159             closeCurrentInput();
   1160             return false;
   1161         }
   1162         if (vh.getLooper() != Looper.myLooper()) {
   1163             // The view is running on a different thread than our own, so
   1164             // we need to reschedule our work for over there.
   1165             if (DEBUG) Log.v(TAG, "Starting input: reschedule to view thread");
   1166             vh.post(new Runnable() {
   1167                 @Override
   1168                 public void run() {
   1169                     startInputInner(null, 0, 0, 0);
   1170                 }
   1171             });
   1172             return false;
   1173         }
   1174 
   1175         // Okay we are now ready to call into the served view and have it
   1176         // do its stuff.
   1177         // Life is good: let's hook everything up!
   1178         EditorInfo tba = new EditorInfo();
   1179         tba.packageName = view.getContext().getPackageName();
   1180         tba.fieldId = view.getId();
   1181         InputConnection ic = view.onCreateInputConnection(tba);
   1182         if (DEBUG) Log.v(TAG, "Starting input: tba=" + tba + " ic=" + ic);
   1183 
   1184         synchronized (mH) {
   1185             // Now that we are locked again, validate that our state hasn't
   1186             // changed.
   1187             if (mServedView != view || !mServedConnecting) {
   1188                 // Something else happened, so abort.
   1189                 if (DEBUG) Log.v(TAG,
   1190                         "Starting input: finished by someone else (view="
   1191                         + mServedView + " conn=" + mServedConnecting + ")");
   1192                 return false;
   1193             }
   1194 
   1195             // If we already have a text box, then this view is already
   1196             // connected so we want to restart it.
   1197             if (mCurrentTextBoxAttribute == null) {
   1198                 controlFlags |= CONTROL_START_INITIAL;
   1199             }
   1200 
   1201             // Hook 'em up and let 'er rip.
   1202             mCurrentTextBoxAttribute = tba;
   1203             mServedConnecting = false;
   1204             // Notify the served view that its previous input connection is finished
   1205             notifyInputConnectionFinished();
   1206             mServedInputConnection = ic;
   1207             ControlledInputConnectionWrapper servedContext;
   1208             if (ic != null) {
   1209                 mCursorSelStart = tba.initialSelStart;
   1210                 mCursorSelEnd = tba.initialSelEnd;
   1211                 mCursorCandStart = -1;
   1212                 mCursorCandEnd = -1;
   1213                 mCursorRect.setEmpty();
   1214                 mCursorAnchorInfo = null;
   1215                 servedContext = new ControlledInputConnectionWrapper(vh.getLooper(), ic, this);
   1216             } else {
   1217                 servedContext = null;
   1218             }
   1219             if (mServedInputConnectionWrapper != null) {
   1220                 mServedInputConnectionWrapper.deactivate();
   1221             }
   1222             mServedInputConnectionWrapper = servedContext;
   1223 
   1224             try {
   1225                 if (DEBUG) Log.v(TAG, "START INPUT: " + view + " ic="
   1226                         + ic + " tba=" + tba + " controlFlags=#"
   1227                         + Integer.toHexString(controlFlags));
   1228                 InputBindResult res;
   1229                 if (windowGainingFocus != null) {
   1230                     res = mService.windowGainedFocus(mClient, windowGainingFocus,
   1231                             controlFlags, softInputMode, windowFlags,
   1232                             tba, servedContext);
   1233                 } else {
   1234                     res = mService.startInput(mClient,
   1235                             servedContext, tba, controlFlags);
   1236                 }
   1237                 if (DEBUG) Log.v(TAG, "Starting input: Bind result=" + res);
   1238                 if (res != null) {
   1239                     if (res.id != null) {
   1240                         setInputChannelLocked(res.channel);
   1241                         mBindSequence = res.sequence;
   1242                         mCurMethod = res.method;
   1243                         mCurId = res.id;
   1244                         mNextUserActionNotificationSequenceNumber =
   1245                                 res.userActionNotificationSequenceNumber;
   1246                     } else {
   1247                         if (res.channel != null && res.channel != mCurChannel) {
   1248                             res.channel.dispose();
   1249                         }
   1250                         if (mCurMethod == null) {
   1251                             // This means there is no input method available.
   1252                             if (DEBUG) Log.v(TAG, "ABORT input: no input method!");
   1253                             return true;
   1254                         }
   1255                     }
   1256                 }
   1257                 if (mCurMethod != null && mCompletions != null) {
   1258                     try {
   1259                         mCurMethod.displayCompletions(mCompletions);
   1260                     } catch (RemoteException e) {
   1261                     }
   1262                 }
   1263             } catch (RemoteException e) {
   1264                 Log.w(TAG, "IME died: " + mCurId, e);
   1265             }
   1266         }
   1267 
   1268         return true;
   1269     }
   1270 
   1271     /**
   1272      * When the focused window is dismissed, this method is called to finish the
   1273      * input method started before.
   1274      * @hide
   1275      */
   1276     public void windowDismissed(IBinder appWindowToken) {
   1277         checkFocus();
   1278         synchronized (mH) {
   1279             if (mServedView != null &&
   1280                     mServedView.getWindowToken() == appWindowToken) {
   1281                 finishInputLocked();
   1282             }
   1283         }
   1284     }
   1285 
   1286     /**
   1287      * Call this when a view receives focus.
   1288      * @hide
   1289      */
   1290     public void focusIn(View view) {
   1291         synchronized (mH) {
   1292             focusInLocked(view);
   1293         }
   1294     }
   1295 
   1296     void focusInLocked(View view) {
   1297         if (DEBUG) Log.v(TAG, "focusIn: " + view);
   1298 
   1299         if (mCurRootView != view.getRootView()) {
   1300             // This is a request from a window that isn't in the window with
   1301             // IME focus, so ignore it.
   1302             if (DEBUG) Log.v(TAG, "Not IME target window, ignoring");
   1303             return;
   1304         }
   1305 
   1306         mNextServedView = view;
   1307         scheduleCheckFocusLocked(view);
   1308     }
   1309 
   1310     /**
   1311      * Call this when a view loses focus.
   1312      * @hide
   1313      */
   1314     public void focusOut(View view) {
   1315         synchronized (mH) {
   1316             if (DEBUG) Log.v(TAG, "focusOut: " + view
   1317                     + " mServedView=" + mServedView
   1318                     + " winFocus=" + view.hasWindowFocus());
   1319             if (mServedView != view) {
   1320                 // The following code would auto-hide the IME if we end up
   1321                 // with no more views with focus.  This can happen, however,
   1322                 // whenever we go into touch mode, so it ends up hiding
   1323                 // at times when we don't really want it to.  For now it
   1324                 // seems better to just turn it all off.
   1325                 if (false && view.hasWindowFocus()) {
   1326                     mNextServedView = null;
   1327                     scheduleCheckFocusLocked(view);
   1328                 }
   1329             }
   1330         }
   1331     }
   1332 
   1333     static void scheduleCheckFocusLocked(View view) {
   1334         ViewRootImpl viewRootImpl = view.getViewRootImpl();
   1335         if (viewRootImpl != null) {
   1336             viewRootImpl.dispatchCheckFocus();
   1337         }
   1338     }
   1339 
   1340     /**
   1341      * @hide
   1342      */
   1343     public void checkFocus() {
   1344         if (checkFocusNoStartInput(false, true)) {
   1345             startInputInner(null, 0, 0, 0);
   1346         }
   1347     }
   1348 
   1349     private boolean checkFocusNoStartInput(boolean forceNewFocus, boolean finishComposingText) {
   1350         // This is called a lot, so short-circuit before locking.
   1351         if (mServedView == mNextServedView && !forceNewFocus) {
   1352             return false;
   1353         }
   1354 
   1355         InputConnection ic = null;
   1356         synchronized (mH) {
   1357             if (mServedView == mNextServedView && !forceNewFocus) {
   1358                 return false;
   1359             }
   1360             if (DEBUG) Log.v(TAG, "checkFocus: view=" + mServedView
   1361                     + " next=" + mNextServedView
   1362                     + " forceNewFocus=" + forceNewFocus
   1363                     + " package="
   1364                     + (mServedView != null ? mServedView.getContext().getPackageName() : "<none>"));
   1365 
   1366             if (mNextServedView == null) {
   1367                 finishInputLocked();
   1368                 // In this case, we used to have a focused view on the window,
   1369                 // but no longer do.  We should make sure the input method is
   1370                 // no longer shown, since it serves no purpose.
   1371                 closeCurrentInput();
   1372                 return false;
   1373             }
   1374 
   1375             ic = mServedInputConnection;
   1376 
   1377             mServedView = mNextServedView;
   1378             mCurrentTextBoxAttribute = null;
   1379             mCompletions = null;
   1380             mServedConnecting = true;
   1381         }
   1382 
   1383         if (finishComposingText && ic != null) {
   1384             ic.finishComposingText();
   1385         }
   1386 
   1387         return true;
   1388     }
   1389 
   1390     void closeCurrentInput() {
   1391         try {
   1392             mService.hideSoftInput(mClient, HIDE_NOT_ALWAYS, null);
   1393         } catch (RemoteException e) {
   1394         }
   1395     }
   1396 
   1397     /**
   1398      * Called by ViewAncestor when its window gets input focus.
   1399      * @hide
   1400      */
   1401     public void onWindowFocus(View rootView, View focusedView, int softInputMode,
   1402             boolean first, int windowFlags) {
   1403         boolean forceNewFocus = false;
   1404         synchronized (mH) {
   1405             if (DEBUG) Log.v(TAG, "onWindowFocus: " + focusedView
   1406                     + " softInputMode=" + softInputMode
   1407                     + " first=" + first + " flags=#"
   1408                     + Integer.toHexString(windowFlags));
   1409             if (mHasBeenInactive) {
   1410                 if (DEBUG) Log.v(TAG, "Has been inactive!  Starting fresh");
   1411                 mHasBeenInactive = false;
   1412                 forceNewFocus = true;
   1413             }
   1414             focusInLocked(focusedView != null ? focusedView : rootView);
   1415         }
   1416 
   1417         int controlFlags = 0;
   1418         if (focusedView != null) {
   1419             controlFlags |= CONTROL_WINDOW_VIEW_HAS_FOCUS;
   1420             if (focusedView.onCheckIsTextEditor()) {
   1421                 controlFlags |= CONTROL_WINDOW_IS_TEXT_EDITOR;
   1422             }
   1423         }
   1424         if (first) {
   1425             controlFlags |= CONTROL_WINDOW_FIRST;
   1426         }
   1427 
   1428         if (checkFocusNoStartInput(forceNewFocus, true)) {
   1429             // We need to restart input on the current focus view.  This
   1430             // should be done in conjunction with telling the system service
   1431             // about the window gaining focus, to help make the transition
   1432             // smooth.
   1433             if (startInputInner(rootView.getWindowToken(),
   1434                     controlFlags, softInputMode, windowFlags)) {
   1435                 return;
   1436             }
   1437         }
   1438 
   1439         // For some reason we didn't do a startInput + windowFocusGain, so
   1440         // we'll just do a window focus gain and call it a day.
   1441         synchronized (mH) {
   1442             try {
   1443                 if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
   1444                 mService.windowGainedFocus(mClient, rootView.getWindowToken(),
   1445                         controlFlags, softInputMode, windowFlags, null, null);
   1446             } catch (RemoteException e) {
   1447             }
   1448         }
   1449     }
   1450 
   1451     /** @hide */
   1452     public void startGettingWindowFocus(View rootView) {
   1453         synchronized (mH) {
   1454             mCurRootView = rootView;
   1455         }
   1456     }
   1457 
   1458     /**
   1459      * Report the current selection range.
   1460      *
   1461      * <p><strong>Editor authors</strong>, you need to call this method whenever
   1462      * the cursor moves in your editor. Remember that in addition to doing this, your
   1463      * editor needs to always supply current cursor values in
   1464      * {@link EditorInfo#initialSelStart} and {@link EditorInfo#initialSelEnd} every
   1465      * time {@link android.view.View#onCreateInputConnection(EditorInfo)} is
   1466      * called, which happens whenever the keyboard shows up or the focus changes
   1467      * to a text field, among other cases.</p>
   1468      */
   1469     public void updateSelection(View view, int selStart, int selEnd,
   1470             int candidatesStart, int candidatesEnd) {
   1471         checkFocus();
   1472         synchronized (mH) {
   1473             if ((mServedView != view && (mServedView == null
   1474                         || !mServedView.checkInputConnectionProxy(view)))
   1475                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
   1476                 return;
   1477             }
   1478 
   1479             if (mCursorSelStart != selStart || mCursorSelEnd != selEnd
   1480                     || mCursorCandStart != candidatesStart
   1481                     || mCursorCandEnd != candidatesEnd) {
   1482                 if (DEBUG) Log.d(TAG, "updateSelection");
   1483 
   1484                 try {
   1485                     if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
   1486                     final int oldSelStart = mCursorSelStart;
   1487                     final int oldSelEnd = mCursorSelEnd;
   1488                     // Update internal values before sending updateSelection to the IME, because
   1489                     // if it changes the text within its onUpdateSelection handler in a way that
   1490                     // does not move the cursor we don't want to call it again with the same values.
   1491                     mCursorSelStart = selStart;
   1492                     mCursorSelEnd = selEnd;
   1493                     mCursorCandStart = candidatesStart;
   1494                     mCursorCandEnd = candidatesEnd;
   1495                     mCurMethod.updateSelection(oldSelStart, oldSelEnd,
   1496                             selStart, selEnd, candidatesStart, candidatesEnd);
   1497                 } catch (RemoteException e) {
   1498                     Log.w(TAG, "IME died: " + mCurId, e);
   1499                 }
   1500             }
   1501         }
   1502     }
   1503 
   1504     /**
   1505      * Notify the event when the user tapped or clicked the text view.
   1506      */
   1507     public void viewClicked(View view) {
   1508         final boolean focusChanged = mServedView != mNextServedView;
   1509         checkFocus();
   1510         synchronized (mH) {
   1511             if ((mServedView != view && (mServedView == null
   1512                     || !mServedView.checkInputConnectionProxy(view)))
   1513                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
   1514                 return;
   1515             }
   1516             try {
   1517                 if (DEBUG) Log.v(TAG, "onViewClicked: " + focusChanged);
   1518                 mCurMethod.viewClicked(focusChanged);
   1519             } catch (RemoteException e) {
   1520                 Log.w(TAG, "IME died: " + mCurId, e);
   1521             }
   1522         }
   1523     }
   1524 
   1525     /**
   1526      * Return true if the current input method wants to watch the location
   1527      * of the input editor's cursor in its window.
   1528      *
   1529      * @deprecated Use {@link InputConnection#requestCursorUpdates(int)} instead.
   1530      */
   1531     @Deprecated
   1532     public boolean isWatchingCursor(View view) {
   1533         return false;
   1534     }
   1535 
   1536     /**
   1537      * Return true if the current input method wants to be notified when cursor/anchor location
   1538      * is changed.
   1539      *
   1540      * @hide
   1541      */
   1542     public boolean isCursorAnchorInfoEnabled() {
   1543         synchronized (mH) {
   1544             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
   1545                     InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
   1546             final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode &
   1547                     InputConnection.CURSOR_UPDATE_MONITOR) != 0;
   1548             return isImmediate || isMonitoring;
   1549         }
   1550     }
   1551 
   1552     /**
   1553      * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
   1554      *
   1555      * @hide
   1556      */
   1557     public void setUpdateCursorAnchorInfoMode(int flags) {
   1558         synchronized (mH) {
   1559             mRequestUpdateCursorAnchorInfoMonitorMode = flags;
   1560         }
   1561     }
   1562 
   1563     /**
   1564      * Report the current cursor location in its window.
   1565      *
   1566      * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead.
   1567      */
   1568     @Deprecated
   1569     public void updateCursor(View view, int left, int top, int right, int bottom) {
   1570         checkFocus();
   1571         synchronized (mH) {
   1572             if ((mServedView != view && (mServedView == null
   1573                         || !mServedView.checkInputConnectionProxy(view)))
   1574                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
   1575                 return;
   1576             }
   1577 
   1578             mTmpCursorRect.set(left, top, right, bottom);
   1579             if (!mCursorRect.equals(mTmpCursorRect)) {
   1580                 if (DEBUG) Log.d(TAG, "updateCursor");
   1581 
   1582                 try {
   1583                     if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
   1584                     mCurMethod.updateCursor(mTmpCursorRect);
   1585                     mCursorRect.set(mTmpCursorRect);
   1586                 } catch (RemoteException e) {
   1587                     Log.w(TAG, "IME died: " + mCurId, e);
   1588                 }
   1589             }
   1590         }
   1591     }
   1592 
   1593     /**
   1594      * Report positional change of the text insertion point and/or characters in the composition
   1595      * string.
   1596      */
   1597     public void updateCursorAnchorInfo(View view, final CursorAnchorInfo cursorAnchorInfo) {
   1598         if (view == null || cursorAnchorInfo == null) {
   1599             return;
   1600         }
   1601         checkFocus();
   1602         synchronized (mH) {
   1603             if ((mServedView != view &&
   1604                     (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
   1605                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
   1606                 return;
   1607             }
   1608             // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
   1609             // not been changed from the previous call.
   1610             final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode &
   1611                     InputConnection.CURSOR_UPDATE_IMMEDIATE) != 0;
   1612             if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
   1613                 // TODO: Consider always emitting this message once we have addressed redundant
   1614                 // calls of this method from android.widget.Editor.
   1615                 if (DEBUG) {
   1616                     Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info="
   1617                             + cursorAnchorInfo);
   1618                 }
   1619                 return;
   1620             }
   1621             if (DEBUG) Log.v(TAG, "updateCursorAnchorInfo: " + cursorAnchorInfo);
   1622             try {
   1623                 mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
   1624                 mCursorAnchorInfo = cursorAnchorInfo;
   1625                 // Clear immediate bit (if any).
   1626                 mRequestUpdateCursorAnchorInfoMonitorMode &=
   1627                         ~InputConnection.CURSOR_UPDATE_IMMEDIATE;
   1628             } catch (RemoteException e) {
   1629                 Log.w(TAG, "IME died: " + mCurId, e);
   1630             }
   1631         }
   1632     }
   1633 
   1634     /**
   1635      * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
   1636      * InputMethodSession.appPrivateCommand()} on the current Input Method.
   1637      * @param view Optional View that is sending the command, or null if
   1638      * you want to send the command regardless of the view that is attached
   1639      * to the input method.
   1640      * @param action Name of the command to be performed.  This <em>must</em>
   1641      * be a scoped name, i.e. prefixed with a package name you own, so that
   1642      * different developers will not create conflicting commands.
   1643      * @param data Any data to include with the command.
   1644      */
   1645     public void sendAppPrivateCommand(View view, String action, Bundle data) {
   1646         checkFocus();
   1647         synchronized (mH) {
   1648             if ((mServedView != view && (mServedView == null
   1649                         || !mServedView.checkInputConnectionProxy(view)))
   1650                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
   1651                 return;
   1652             }
   1653             try {
   1654                 if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
   1655                 mCurMethod.appPrivateCommand(action, data);
   1656             } catch (RemoteException e) {
   1657                 Log.w(TAG, "IME died: " + mCurId, e);
   1658             }
   1659         }
   1660     }
   1661 
   1662     /**
   1663      * Force switch to a new input method component. This can only be called
   1664      * from an application or a service which has a token of the currently active input method.
   1665      * @param token Supplies the identifying token given to an input method
   1666      * when it was started, which allows it to perform this operation on
   1667      * itself.
   1668      * @param id The unique identifier for the new input method to be switched to.
   1669      */
   1670     public void setInputMethod(IBinder token, String id) {
   1671         try {
   1672             mService.setInputMethod(token, id);
   1673         } catch (RemoteException e) {
   1674             throw new RuntimeException(e);
   1675         }
   1676     }
   1677 
   1678     /**
   1679      * Force switch to a new input method and subtype. This can only be called
   1680      * from an application or a service which has a token of the currently active input method.
   1681      * @param token Supplies the identifying token given to an input method
   1682      * when it was started, which allows it to perform this operation on
   1683      * itself.
   1684      * @param id The unique identifier for the new input method to be switched to.
   1685      * @param subtype The new subtype of the new input method to be switched to.
   1686      */
   1687     public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
   1688         try {
   1689             mService.setInputMethodAndSubtype(token, id, subtype);
   1690         } catch (RemoteException e) {
   1691             throw new RuntimeException(e);
   1692         }
   1693     }
   1694 
   1695     /**
   1696      * Close/hide the input method's soft input area, so the user no longer
   1697      * sees it or can interact with it.  This can only be called
   1698      * from the currently active input method, as validated by the given token.
   1699      *
   1700      * @param token Supplies the identifying token given to an input method
   1701      * when it was started, which allows it to perform this operation on
   1702      * itself.
   1703      * @param flags Provides additional operating flags.  Currently may be
   1704      * 0 or have the {@link #HIDE_IMPLICIT_ONLY},
   1705      * {@link #HIDE_NOT_ALWAYS} bit set.
   1706      */
   1707     public void hideSoftInputFromInputMethod(IBinder token, int flags) {
   1708         try {
   1709             mService.hideMySoftInput(token, flags);
   1710         } catch (RemoteException e) {
   1711             throw new RuntimeException(e);
   1712         }
   1713     }
   1714 
   1715     /**
   1716      * Show the input method's soft input area, so the user
   1717      * sees the input method window and can interact with it.
   1718      * This can only be called from the currently active input method,
   1719      * as validated by the given token.
   1720      *
   1721      * @param token Supplies the identifying token given to an input method
   1722      * when it was started, which allows it to perform this operation on
   1723      * itself.
   1724      * @param flags Provides additional operating flags.  Currently may be
   1725      * 0 or have the {@link #SHOW_IMPLICIT} or
   1726      * {@link #SHOW_FORCED} bit set.
   1727      */
   1728     public void showSoftInputFromInputMethod(IBinder token, int flags) {
   1729         try {
   1730             mService.showMySoftInput(token, flags);
   1731         } catch (RemoteException e) {
   1732             throw new RuntimeException(e);
   1733         }
   1734     }
   1735 
   1736     /**
   1737      * Dispatches an input event to the IME.
   1738      *
   1739      * Returns {@link #DISPATCH_HANDLED} if the event was handled.
   1740      * Returns {@link #DISPATCH_NOT_HANDLED} if the event was not handled.
   1741      * Returns {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the
   1742      * callback will be invoked later.
   1743      *
   1744      * @hide
   1745      */
   1746     public int dispatchInputEvent(InputEvent event, Object token,
   1747             FinishedInputEventCallback callback, Handler handler) {
   1748         synchronized (mH) {
   1749             if (mCurMethod != null) {
   1750                 if (event instanceof KeyEvent) {
   1751                     KeyEvent keyEvent = (KeyEvent)event;
   1752                     if (keyEvent.getAction() == KeyEvent.ACTION_DOWN
   1753                             && keyEvent.getKeyCode() == KeyEvent.KEYCODE_SYM
   1754                             && keyEvent.getRepeatCount() == 0) {
   1755                         showInputMethodPickerLocked();
   1756                         return DISPATCH_HANDLED;
   1757                     }
   1758                 }
   1759 
   1760                 if (DEBUG) Log.v(TAG, "DISPATCH INPUT EVENT: " + mCurMethod);
   1761 
   1762                 PendingEvent p = obtainPendingEventLocked(
   1763                         event, token, mCurId, callback, handler);
   1764                 if (mMainLooper.isCurrentThread()) {
   1765                     // Already running on the IMM thread so we can send the event immediately.
   1766                     return sendInputEventOnMainLooperLocked(p);
   1767                 }
   1768 
   1769                 // Post the event to the IMM thread.
   1770                 Message msg = mH.obtainMessage(MSG_SEND_INPUT_EVENT, p);
   1771                 msg.setAsynchronous(true);
   1772                 mH.sendMessage(msg);
   1773                 return DISPATCH_IN_PROGRESS;
   1774             }
   1775         }
   1776         return DISPATCH_NOT_HANDLED;
   1777     }
   1778 
   1779     // Must be called on the main looper
   1780     void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
   1781         final boolean handled;
   1782         synchronized (mH) {
   1783             int result = sendInputEventOnMainLooperLocked(p);
   1784             if (result == DISPATCH_IN_PROGRESS) {
   1785                 return;
   1786             }
   1787 
   1788             handled = (result == DISPATCH_HANDLED);
   1789         }
   1790 
   1791         invokeFinishedInputEventCallback(p, handled);
   1792     }
   1793 
   1794     // Must be called on the main looper
   1795     int sendInputEventOnMainLooperLocked(PendingEvent p) {
   1796         if (mCurChannel != null) {
   1797             if (mCurSender == null) {
   1798                 mCurSender = new ImeInputEventSender(mCurChannel, mH.getLooper());
   1799             }
   1800 
   1801             final InputEvent event = p.mEvent;
   1802             final int seq = event.getSequenceNumber();
   1803             if (mCurSender.sendInputEvent(seq, event)) {
   1804                 mPendingEvents.put(seq, p);
   1805                 Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER,
   1806                         mPendingEvents.size());
   1807 
   1808                 Message msg = mH.obtainMessage(MSG_TIMEOUT_INPUT_EVENT, p);
   1809                 msg.setAsynchronous(true);
   1810                 mH.sendMessageDelayed(msg, INPUT_METHOD_NOT_RESPONDING_TIMEOUT);
   1811                 return DISPATCH_IN_PROGRESS;
   1812             }
   1813 
   1814             Log.w(TAG, "Unable to send input event to IME: "
   1815                     + mCurId + " dropping: " + event);
   1816         }
   1817         return DISPATCH_NOT_HANDLED;
   1818     }
   1819 
   1820     void finishedInputEvent(int seq, boolean handled, boolean timeout) {
   1821         final PendingEvent p;
   1822         synchronized (mH) {
   1823             int index = mPendingEvents.indexOfKey(seq);
   1824             if (index < 0) {
   1825                 return; // spurious, event already finished or timed out
   1826             }
   1827 
   1828             p = mPendingEvents.valueAt(index);
   1829             mPendingEvents.removeAt(index);
   1830             Trace.traceCounter(Trace.TRACE_TAG_INPUT, PENDING_EVENT_COUNTER, mPendingEvents.size());
   1831 
   1832             if (timeout) {
   1833                 Log.w(TAG, "Timeout waiting for IME to handle input event after "
   1834                         + INPUT_METHOD_NOT_RESPONDING_TIMEOUT + " ms: " + p.mInputMethodId);
   1835             } else {
   1836                 mH.removeMessages(MSG_TIMEOUT_INPUT_EVENT, p);
   1837             }
   1838         }
   1839 
   1840         invokeFinishedInputEventCallback(p, handled);
   1841     }
   1842 
   1843     // Assumes the event has already been removed from the queue.
   1844     void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
   1845         p.mHandled = handled;
   1846         if (p.mHandler.getLooper().isCurrentThread()) {
   1847             // Already running on the callback handler thread so we can send the
   1848             // callback immediately.
   1849             p.run();
   1850         } else {
   1851             // Post the event to the callback handler thread.
   1852             // In this case, the callback will be responsible for recycling the event.
   1853             Message msg = Message.obtain(p.mHandler, p);
   1854             msg.setAsynchronous(true);
   1855             msg.sendToTarget();
   1856         }
   1857     }
   1858 
   1859     private void flushPendingEventsLocked() {
   1860         mH.removeMessages(MSG_FLUSH_INPUT_EVENT);
   1861 
   1862         final int count = mPendingEvents.size();
   1863         for (int i = 0; i < count; i++) {
   1864             int seq = mPendingEvents.keyAt(i);
   1865             Message msg = mH.obtainMessage(MSG_FLUSH_INPUT_EVENT, seq, 0);
   1866             msg.setAsynchronous(true);
   1867             msg.sendToTarget();
   1868         }
   1869     }
   1870 
   1871     private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
   1872             String inputMethodId, FinishedInputEventCallback callback, Handler handler) {
   1873         PendingEvent p = mPendingEventPool.acquire();
   1874         if (p == null) {
   1875             p = new PendingEvent();
   1876         }
   1877         p.mEvent = event;
   1878         p.mToken = token;
   1879         p.mInputMethodId = inputMethodId;
   1880         p.mCallback = callback;
   1881         p.mHandler = handler;
   1882         return p;
   1883     }
   1884 
   1885     private void recyclePendingEventLocked(PendingEvent p) {
   1886         p.recycle();
   1887         mPendingEventPool.release(p);
   1888     }
   1889 
   1890     public void showInputMethodPicker() {
   1891         synchronized (mH) {
   1892             showInputMethodPickerLocked();
   1893         }
   1894     }
   1895 
   1896     private void showInputMethodPickerLocked() {
   1897         try {
   1898             mService.showInputMethodPickerFromClient(mClient);
   1899         } catch (RemoteException e) {
   1900             Log.w(TAG, "IME died: " + mCurId, e);
   1901         }
   1902     }
   1903 
   1904     /**
   1905      * Show the settings for enabling subtypes of the specified input method.
   1906      * @param imiId An input method, whose subtypes settings will be shown. If imiId is null,
   1907      * subtypes of all input methods will be shown.
   1908      */
   1909     public void showInputMethodAndSubtypeEnabler(String imiId) {
   1910         synchronized (mH) {
   1911             try {
   1912                 mService.showInputMethodAndSubtypeEnablerFromClient(mClient, imiId);
   1913             } catch (RemoteException e) {
   1914                 Log.w(TAG, "IME died: " + mCurId, e);
   1915             }
   1916         }
   1917     }
   1918 
   1919     /**
   1920      * Returns the current input method subtype. This subtype is one of the subtypes in
   1921      * the current input method. This method returns null when the current input method doesn't
   1922      * have any input method subtype.
   1923      */
   1924     public InputMethodSubtype getCurrentInputMethodSubtype() {
   1925         synchronized (mH) {
   1926             try {
   1927                 return mService.getCurrentInputMethodSubtype();
   1928             } catch (RemoteException e) {
   1929                 Log.w(TAG, "IME died: " + mCurId, e);
   1930                 return null;
   1931             }
   1932         }
   1933     }
   1934 
   1935     /**
   1936      * Switch to a new input method subtype of the current input method.
   1937      * @param subtype A new input method subtype to switch.
   1938      * @return true if the current subtype was successfully switched. When the specified subtype is
   1939      * null, this method returns false.
   1940      */
   1941     public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
   1942         synchronized (mH) {
   1943             try {
   1944                 return mService.setCurrentInputMethodSubtype(subtype);
   1945             } catch (RemoteException e) {
   1946                 Log.w(TAG, "IME died: " + mCurId, e);
   1947                 return false;
   1948             }
   1949         }
   1950     }
   1951 
   1952     /**
   1953      * Notify that a user took some action with this input method.
   1954      * @hide
   1955      */
   1956     public void notifyUserAction() {
   1957         synchronized (mH) {
   1958             if (mLastSentUserActionNotificationSequenceNumber ==
   1959                     mNextUserActionNotificationSequenceNumber) {
   1960                 if (DEBUG) {
   1961                     Log.w(TAG, "Ignoring notifyUserAction as it has already been sent."
   1962                             + " mLastSentUserActionNotificationSequenceNumber: "
   1963                             + mLastSentUserActionNotificationSequenceNumber
   1964                             + " mNextUserActionNotificationSequenceNumber: "
   1965                             + mNextUserActionNotificationSequenceNumber);
   1966                 }
   1967                 return;
   1968             }
   1969             try {
   1970                 if (DEBUG) {
   1971                     Log.w(TAG, "notifyUserAction: "
   1972                             + " mLastSentUserActionNotificationSequenceNumber: "
   1973                             + mLastSentUserActionNotificationSequenceNumber
   1974                             + " mNextUserActionNotificationSequenceNumber: "
   1975                             + mNextUserActionNotificationSequenceNumber);
   1976                 }
   1977                 mService.notifyUserAction(mNextUserActionNotificationSequenceNumber);
   1978                 mLastSentUserActionNotificationSequenceNumber =
   1979                         mNextUserActionNotificationSequenceNumber;
   1980             } catch (RemoteException e) {
   1981                 Log.w(TAG, "IME died: " + mCurId, e);
   1982             }
   1983         }
   1984     }
   1985 
   1986     /**
   1987      * Returns a map of all shortcut input method info and their subtypes.
   1988      */
   1989     public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
   1990         synchronized (mH) {
   1991             HashMap<InputMethodInfo, List<InputMethodSubtype>> ret =
   1992                     new HashMap<InputMethodInfo, List<InputMethodSubtype>>();
   1993             try {
   1994                 // TODO: We should change the return type from List<Object> to List<Parcelable>
   1995                 List<Object> info = mService.getShortcutInputMethodsAndSubtypes();
   1996                 // "info" has imi1, subtype1, subtype2, imi2, subtype2, imi3, subtype3..in the list
   1997                 ArrayList<InputMethodSubtype> subtypes = null;
   1998                 final int N = info.size();
   1999                 if (info != null && N > 0) {
   2000                     for (int i = 0; i < N; ++i) {
   2001                         Object o = info.get(i);
   2002                         if (o instanceof InputMethodInfo) {
   2003                             if (ret.containsKey(o)) {
   2004                                 Log.e(TAG, "IMI list already contains the same InputMethod.");
   2005                                 break;
   2006                             }
   2007                             subtypes = new ArrayList<InputMethodSubtype>();
   2008                             ret.put((InputMethodInfo)o, subtypes);
   2009                         } else if (subtypes != null && o instanceof InputMethodSubtype) {
   2010                             subtypes.add((InputMethodSubtype)o);
   2011                         }
   2012                     }
   2013                 }
   2014             } catch (RemoteException e) {
   2015                 Log.w(TAG, "IME died: " + mCurId, e);
   2016             }
   2017             return ret;
   2018         }
   2019     }
   2020 
   2021     /**
   2022      * @return The current height of the input method window.
   2023      * @hide
   2024      */
   2025     public int getInputMethodWindowVisibleHeight() {
   2026         synchronized (mH) {
   2027             try {
   2028                 return mService.getInputMethodWindowVisibleHeight();
   2029             } catch (RemoteException e) {
   2030                 Log.w(TAG, "IME died: " + mCurId, e);
   2031                 return 0;
   2032             }
   2033         }
   2034     }
   2035 
   2036     /**
   2037      * Force switch to the last used input method and subtype. If the last input method didn't have
   2038      * any subtypes, the framework will simply switch to the last input method with no subtype
   2039      * specified.
   2040      * @param imeToken Supplies the identifying token given to an input method when it was started,
   2041      * which allows it to perform this operation on itself.
   2042      * @return true if the current input method and subtype was successfully switched to the last
   2043      * used input method and subtype.
   2044      */
   2045     public boolean switchToLastInputMethod(IBinder imeToken) {
   2046         synchronized (mH) {
   2047             try {
   2048                 return mService.switchToLastInputMethod(imeToken);
   2049             } catch (RemoteException e) {
   2050                 Log.w(TAG, "IME died: " + mCurId, e);
   2051                 return false;
   2052             }
   2053         }
   2054     }
   2055 
   2056     /**
   2057      * Force switch to the next input method and subtype. If there is no IME enabled except
   2058      * current IME and subtype, do nothing.
   2059      * @param imeToken Supplies the identifying token given to an input method when it was started,
   2060      * which allows it to perform this operation on itself.
   2061      * @param onlyCurrentIme if true, the framework will find the next subtype which
   2062      * belongs to the current IME
   2063      * @return true if the current input method and subtype was successfully switched to the next
   2064      * input method and subtype.
   2065      */
   2066     public boolean switchToNextInputMethod(IBinder imeToken, boolean onlyCurrentIme) {
   2067         synchronized (mH) {
   2068             try {
   2069                 return mService.switchToNextInputMethod(imeToken, onlyCurrentIme);
   2070             } catch (RemoteException e) {
   2071                 Log.w(TAG, "IME died: " + mCurId, e);
   2072                 return false;
   2073             }
   2074         }
   2075     }
   2076 
   2077     /**
   2078      * Returns true if the current IME needs to offer the users ways to switch to a next input
   2079      * method (e.g. a globe key.).
   2080      * When an IME sets supportsSwitchingToNextInputMethod and this method returns true,
   2081      * the IME has to offer ways to to invoke {@link #switchToNextInputMethod} accordingly.
   2082      * <p> Note that the system determines the most appropriate next input method
   2083      * and subtype in order to provide the consistent user experience in switching
   2084      * between IMEs and subtypes.
   2085      * @param imeToken Supplies the identifying token given to an input method when it was started,
   2086      * which allows it to perform this operation on itself.
   2087      */
   2088     public boolean shouldOfferSwitchingToNextInputMethod(IBinder imeToken) {
   2089         synchronized (mH) {
   2090             try {
   2091                 return mService.shouldOfferSwitchingToNextInputMethod(imeToken);
   2092             } catch (RemoteException e) {
   2093                 Log.w(TAG, "IME died: " + mCurId, e);
   2094                 return false;
   2095             }
   2096         }
   2097     }
   2098 
   2099     /**
   2100      * Set additional input method subtypes. Only a process which shares the same uid with the IME
   2101      * can add additional input method subtypes to the IME.
   2102      * Please note that a subtype's status is stored in the system.
   2103      * For example, enabled subtypes are remembered by the framework even after they are removed
   2104      * by using this method. If you re-add the same subtypes again,
   2105      * they will just get enabled. If you want to avoid such conflicts, for instance, you may
   2106      * want to create a "different" new subtype even with the same locale and mode,
   2107      * by changing its extra value. The different subtype won't get affected by the stored past
   2108      * status. (You may want to take a look at {@link InputMethodSubtype#hashCode()} to refer
   2109      * to the current implementation.)
   2110      * @param imiId Id of InputMethodInfo which additional input method subtypes will be added to.
   2111      * @param subtypes subtypes will be added as additional subtypes of the current input method.
   2112      */
   2113     public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
   2114         synchronized (mH) {
   2115             try {
   2116                 mService.setAdditionalInputMethodSubtypes(imiId, subtypes);
   2117             } catch (RemoteException e) {
   2118                 Log.w(TAG, "IME died: " + mCurId, e);
   2119             }
   2120         }
   2121     }
   2122 
   2123     public InputMethodSubtype getLastInputMethodSubtype() {
   2124         synchronized (mH) {
   2125             try {
   2126                 return mService.getLastInputMethodSubtype();
   2127             } catch (RemoteException e) {
   2128                 Log.w(TAG, "IME died: " + mCurId, e);
   2129                 return null;
   2130             }
   2131         }
   2132     }
   2133 
   2134     void doDump(FileDescriptor fd, PrintWriter fout, String[] args) {
   2135         final Printer p = new PrintWriterPrinter(fout);
   2136         p.println("Input method client state for " + this + ":");
   2137 
   2138         p.println("  mService=" + mService);
   2139         p.println("  mMainLooper=" + mMainLooper);
   2140         p.println("  mIInputContext=" + mIInputContext);
   2141         p.println("  mActive=" + mActive
   2142                 + " mHasBeenInactive=" + mHasBeenInactive
   2143                 + " mBindSequence=" + mBindSequence
   2144                 + " mCurId=" + mCurId);
   2145         p.println("  mCurMethod=" + mCurMethod);
   2146         p.println("  mCurRootView=" + mCurRootView);
   2147         p.println("  mServedView=" + mServedView);
   2148         p.println("  mNextServedView=" + mNextServedView);
   2149         p.println("  mServedConnecting=" + mServedConnecting);
   2150         if (mCurrentTextBoxAttribute != null) {
   2151             p.println("  mCurrentTextBoxAttribute:");
   2152             mCurrentTextBoxAttribute.dump(p, "    ");
   2153         } else {
   2154             p.println("  mCurrentTextBoxAttribute: null");
   2155         }
   2156         p.println("  mServedInputConnection=" + mServedInputConnection);
   2157         p.println("  mCompletions=" + mCompletions);
   2158         p.println("  mCursorRect=" + mCursorRect);
   2159         p.println("  mCursorSelStart=" + mCursorSelStart
   2160                 + " mCursorSelEnd=" + mCursorSelEnd
   2161                 + " mCursorCandStart=" + mCursorCandStart
   2162                 + " mCursorCandEnd=" + mCursorCandEnd);
   2163         p.println("  mNextUserActionNotificationSequenceNumber="
   2164                 + mNextUserActionNotificationSequenceNumber
   2165                 + " mLastSentUserActionNotificationSequenceNumber="
   2166                 + mLastSentUserActionNotificationSequenceNumber);
   2167     }
   2168 
   2169     /**
   2170      * Callback that is invoked when an input event that was dispatched to
   2171      * the IME has been finished.
   2172      * @hide
   2173      */
   2174     public interface FinishedInputEventCallback {
   2175         public void onFinishedInputEvent(Object token, boolean handled);
   2176     }
   2177 
   2178     private final class ImeInputEventSender extends InputEventSender {
   2179         public ImeInputEventSender(InputChannel inputChannel, Looper looper) {
   2180             super(inputChannel, looper);
   2181         }
   2182 
   2183         @Override
   2184         public void onInputEventFinished(int seq, boolean handled) {
   2185             finishedInputEvent(seq, handled, false);
   2186         }
   2187     }
   2188 
   2189     private final class PendingEvent implements Runnable {
   2190         public InputEvent mEvent;
   2191         public Object mToken;
   2192         public String mInputMethodId;
   2193         public FinishedInputEventCallback mCallback;
   2194         public Handler mHandler;
   2195         public boolean mHandled;
   2196 
   2197         public void recycle() {
   2198             mEvent = null;
   2199             mToken = null;
   2200             mInputMethodId = null;
   2201             mCallback = null;
   2202             mHandler = null;
   2203             mHandled = false;
   2204         }
   2205 
   2206         @Override
   2207         public void run() {
   2208             mCallback.onFinishedInputEvent(mToken, mHandled);
   2209 
   2210             synchronized (mH) {
   2211                 recyclePendingEventLocked(this);
   2212             }
   2213         }
   2214     }
   2215 }
   2216