/** Report the current selection range. */
  public void updateSelection(
      View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd) {
    checkFocus();
    synchronized (mH) {
      if ((mServedView != view
              && (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
          || mCurrentTextBoxAttribute == null
          || mCurMethod == null) {
        return;
      }

      if (mCursorSelStart != selStart
          || mCursorSelEnd != selEnd
          || mCursorCandStart != candidatesStart
          || mCursorCandEnd != candidatesEnd) {
        if (DEBUG) Log.d(TAG, "updateSelection");

        try {
          if (DEBUG) Log.v(TAG, "SELECTION CHANGE: " + mCurMethod);
          mCurMethod.updateSelection(
              mCursorSelStart, mCursorSelEnd, selStart, selEnd, candidatesStart, candidatesEnd);
          mCursorSelStart = selStart;
          mCursorSelEnd = selEnd;
          mCursorCandStart = candidatesStart;
          mCursorCandEnd = candidatesEnd;
        } catch (RemoteException e) {
          Log.w(TAG, "IME died: " + mCurId, e);
        }
      }
    }
  }
 /** Return true if the given view is the currently active view for the input method. */
 public boolean isActive(View view) {
   checkFocus();
   synchronized (mH) {
     return (mServedView == view
             || (mServedView != null && mServedView.checkInputConnectionProxy(view)))
         && mCurrentTextBoxAttribute != null;
   }
 }
  /**
   * If the input method is currently connected to the given view, restart it with its new contents.
   * You should call this when the text within your view changes outside of the normal input method
   * or key input flow, such as when an application calls TextView.setText().
   *
   * @param view The view whose text has changed.
   */
  public void restartInput(View view) {
    checkFocus();
    synchronized (mH) {
      if (mServedView != view
          && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) {
        return;
      }

      mServedConnecting = true;
    }

    startInputInner();
  }
  /**
   * Explicitly request that the current input method's soft input area be shown to the user, if
   * needed. Call this if the user interacts with your view in such a way that they have expressed
   * they would like to start performing input into it.
   *
   * @param view The currently focused view, which would like to receive soft keyboard input.
   * @param flags Provides additional operating flags. Currently may be 0 or have the {@link
   *     #SHOW_IMPLICIT} bit set.
   * @param resultReceiver If non-null, this will be called by the IME when it has processed your
   *     request to tell you what it has done. The result code you receive may be either {@link
   *     #RESULT_UNCHANGED_SHOWN}, {@link #RESULT_UNCHANGED_HIDDEN}, {@link #RESULT_SHOWN}, or
   *     {@link #RESULT_HIDDEN}.
   */
  public boolean showSoftInput(View view, int flags, ResultReceiver resultReceiver) {
    checkFocus();
    synchronized (mH) {
      if (mServedView != view
          && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) {
        return false;
      }

      try {
        return mService.showSoftInput(mClient, flags, resultReceiver);
      } catch (RemoteException e) {
      }

      return false;
    }
  }
  public void updateExtractedText(View view, int token, ExtractedText text) {
    checkFocus();
    synchronized (mH) {
      if (mServedView != view
          && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) {
        return;
      }

      if (mCurMethod != null) {
        try {
          mCurMethod.updateExtractedText(token, text);
        } catch (RemoteException e) {
        }
      }
    }
  }
  public void displayCompletions(View view, CompletionInfo[] completions) {
    checkFocus();
    synchronized (mH) {
      if (mServedView != view
          && (mServedView == null || !mServedView.checkInputConnectionProxy(view))) {
        return;
      }

      mCompletions = completions;
      if (mCurMethod != null) {
        try {
          mCurMethod.displayCompletions(mCompletions);
        } catch (RemoteException e) {
        }
      }
    }
  }
 /**
  * Call {@link InputMethodSession#appPrivateCommand(String, Bundle)
  * InputMethodSession.appPrivateCommand()} on the current Input Method.
  *
  * @param view Optional View that is sending the command, or null if you want to send the command
  *     regardless of the view that is attached to the input method.
  * @param action Name of the command to be performed. This <em>must</em> be a scoped name, i.e.
  *     prefixed with a package name you own, so that different developers will not create
  *     conflicting commands.
  * @param data Any data to include with the command.
  */
 public void sendAppPrivateCommand(View view, String action, Bundle data) {
   checkFocus();
   synchronized (mH) {
     if ((mServedView != view
             && (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
         || mCurrentTextBoxAttribute == null
         || mCurMethod == null) {
       return;
     }
     try {
       if (DEBUG) Log.v(TAG, "APP PRIVATE COMMAND " + action + ": " + data);
       mCurMethod.appPrivateCommand(action, data);
     } catch (RemoteException e) {
       Log.w(TAG, "IME died: " + mCurId, e);
     }
   }
 }
  /** Report the current cursor location in its window. */
  public void updateCursor(View view, int left, int top, int right, int bottom) {
    checkFocus();
    synchronized (mH) {
      if ((mServedView != view
              && (mServedView == null || !mServedView.checkInputConnectionProxy(view)))
          || mCurrentTextBoxAttribute == null
          || mCurMethod == null) {
        return;
      }

      mTmpCursorRect.set(left, top, right, bottom);
      if (!mCursorRect.equals(mTmpCursorRect)) {
        if (DEBUG) Log.d(TAG, "updateCursor");

        try {
          if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
          mCurMethod.updateCursor(mTmpCursorRect);
          mCursorRect.set(mTmpCursorRect);
        } catch (RemoteException e) {
          Log.w(TAG, "IME died: " + mCurId, e);
        }
      }
    }
  }