@Override
  protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
    AbstractInputMethodService target = mTarget.get();
    if (target == null) {
      return;
    }
    if (target.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
        != PackageManager.PERMISSION_GRANTED) {

      fout.println(
          "Permission Denial: can't dump InputMethodManager from from pid="
              + Binder.getCallingPid()
              + ", uid="
              + Binder.getCallingUid());
      return;
    }

    CountDownLatch latch = new CountDownLatch(1);
    mCaller.executeOrSendMessage(mCaller.obtainMessageOOOO(DO_DUMP, fd, fout, args, latch));
    try {
      if (!latch.await(5, TimeUnit.SECONDS)) {
        fout.println("Timeout waiting for dump");
      }
    } catch (InterruptedException e) {
      fout.println("Interrupted waiting for dump");
    }
  }
 @Override
 public void dispatchAppVisibility(boolean visible) {
   // We don't do this in preview mode; we'll let the preview
   // activity tell us when to run.
   if (!mIWallpaperEngine.mIsPreview) {
     Message msg = mCaller.obtainMessageI(MSG_VISIBILITY_CHANGED, visible ? 1 : 0);
     mCaller.sendMessage(msg);
   }
 }
 public void revokeSession(IInputMethodSession session) {
   try {
     InputMethodSession ls =
         ((IInputMethodSessionWrapper) session).getInternalInputMethodSession();
     mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_REVOKE_SESSION, ls));
   } catch (ClassCastException e) {
     Log.w(TAG, "Incoming session not of correct type: " + session, e);
   }
 }
 public void setSessionEnabled(IInputMethodSession session, boolean enabled) {
   try {
     InputMethodSession ls =
         ((IInputMethodSessionWrapper) session).getInternalInputMethodSession();
     mCaller.executeOrSendMessage(
         mCaller.obtainMessageIO(DO_SET_SESSION_ENABLED, enabled ? 1 : 0, ls));
   } catch (ClassCastException e) {
     Log.w(TAG, "Incoming session not of correct type: " + session, e);
   }
 }
 @Override
 public void resized(
     Rect frame,
     Rect contentInsets,
     Rect visibleInsets,
     boolean reportDraw,
     Configuration newConfig) {
   Message msg = mCaller.obtainMessageI(MSG_WINDOW_RESIZED, reportDraw ? 1 : 0);
   mCaller.sendMessage(msg);
 }
  public void createPrintJob(PrintJobInfo printJob) {
    synchronized (mLock) {
      addPrintJobLocked(printJob);
      setPrintJobState(printJob.getId(), PrintJobInfo.STATE_CREATED, null);

      Message message =
          mHandlerCaller.obtainMessageO(
              HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, printJob);
      mHandlerCaller.executeOrSendMessage(message);
    }
  }
 private void dispatchPointer(MotionEvent event) {
   if (event.isTouchEvent()) {
     synchronized (mLock) {
       if (event.getAction() == MotionEvent.ACTION_MOVE) {
         mPendingMove = event;
       } else {
         mPendingMove = null;
       }
     }
     Message msg = mCaller.obtainMessageO(MSG_TOUCH_EVENT, event);
     mCaller.sendMessage(msg);
   } else {
     event.recycle();
   }
 }
 @Override
 public IVoiceInteractorRequest startCommand(
     String callingPackage,
     IVoiceInteractorCallback callback,
     String command,
     Bundle extras) {
   Request request = newRequest(callback);
   mHandlerCaller.sendMessage(
       mHandlerCaller.obtainMessageOOOO(
           MSG_START_COMMAND,
           new Caller(callingPackage, Binder.getCallingUid()),
           request,
           command,
           extras));
   return request.mInterface;
 }
 @Override
 public IVoiceInteractorRequest startConfirmation(
     String callingPackage,
     IVoiceInteractorCallback callback,
     CharSequence prompt,
     Bundle extras) {
   Request request = newRequest(callback);
   mHandlerCaller.sendMessage(
       mHandlerCaller.obtainMessageOOOO(
           MSG_START_CONFIRMATION,
           new Caller(callingPackage, Binder.getCallingUid()),
           request,
           prompt,
           extras));
   return request.mInterface;
 }
 @Override
 public IVoiceInteractorRequest startAbortVoice(
     String callingPackage,
     IVoiceInteractorCallback callback,
     CharSequence message,
     Bundle extras) {
   Request request = newRequest(callback);
   mHandlerCaller.sendMessage(
       mHandlerCaller.obtainMessageOOOO(
           MSG_START_ABORT_VOICE,
           new Caller(callingPackage, Binder.getCallingUid()),
           request,
           message,
           extras));
   return request.mInterface;
 }
 @Override
 public boolean[] supportsCommands(String callingPackage, String[] commands) {
   Message msg =
       mHandlerCaller.obtainMessageIOO(
           MSG_SUPPORTS_COMMANDS,
           0,
           new Caller(callingPackage, Binder.getCallingUid()),
           commands);
   SomeArgs args = mHandlerCaller.sendMessageAndWait(msg);
   if (args != null) {
     boolean[] res = (boolean[]) args.arg1;
     args.recycle();
     return res;
   }
   return new boolean[commands.length];
 }
 @Override
 public void dispatchWallpaperCommand(
     String action, int x, int y, int z, Bundle extras, boolean sync) {
   synchronized (mLock) {
     if (DEBUG) Log.v(TAG, "Dispatch wallpaper command: " + x + ", " + y);
     WallpaperCommand cmd = new WallpaperCommand();
     cmd.action = action;
     cmd.x = x;
     cmd.y = y;
     cmd.z = z;
     cmd.extras = extras;
     cmd.sync = sync;
     Message msg = mCaller.obtainMessage(MSG_WALLPAPER_COMMAND);
     msg.obj = cmd;
     mCaller.sendMessage(msg);
   }
 }
  public void setPrintJobCancelling(PrintJobId printJobId, boolean cancelling) {
    synchronized (mLock) {
      PrintJobInfo printJob = getPrintJobInfo(printJobId, PrintManager.APP_ID_ANY);
      if (printJob != null) {
        printJob.setCancelling(cancelling);
        if (shouldPersistPrintJob(printJob)) {
          mPersistanceManager.writeStateLocked();
        }
        mNotificationController.onUpdateNotifications(mPrintJobs);

        Message message =
            mHandlerCaller.obtainMessageO(
                HandlerCallerCallback.MSG_ON_PRINT_JOB_STATE_CHANGED, printJob);
        mHandlerCaller.executeOrSendMessage(message);
      }
    }
  }
 @Override
 public void dispatchWallpaperOffsets(
     float x, float y, float xStep, float yStep, boolean sync) {
   synchronized (mLock) {
     if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
     mPendingXOffset = x;
     mPendingYOffset = y;
     mPendingXOffsetStep = xStep;
     mPendingYOffsetStep = yStep;
     if (sync) {
       mPendingSync = true;
     }
     if (!mOffsetMessageEnqueued) {
       mOffsetMessageEnqueued = true;
       Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
       mCaller.sendMessage(msg);
     }
   }
 }
    IWallpaperEngineWrapper(
        WallpaperService context,
        IWallpaperConnection conn,
        IBinder windowToken,
        int windowType,
        boolean isPreview,
        int reqWidth,
        int reqHeight) {
      if (DEBUG && mCallbackLooper != null) {
        mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
      }
      mCaller =
          new HandlerCaller(
              context, mCallbackLooper != null ? mCallbackLooper : context.getMainLooper(), this);
      mConnection = conn;
      mWindowToken = windowToken;
      mWindowType = windowType;
      mIsPreview = isPreview;
      mReqWidth = reqWidth;
      mReqHeight = reqHeight;

      Message msg = mCaller.obtainMessage(DO_ATTACH);
      mCaller.sendMessage(msg);
    }
 public void unbindInput() {
   mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_UNSET_INPUT_CONTEXT));
 }
 public void bindInput(InputBinding binding) {
   InputConnection ic =
       new InputConnectionWrapper(IInputContext.Stub.asInterface(binding.getConnectionToken()));
   InputBinding nu = new InputBinding(ic, binding);
   mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_SET_INPUT_CONTEXT, nu));
 }
 public void attachToken(IBinder token) {
   mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_ATTACH_TOKEN, token));
 }
 public void destroy() {
   Message msg = mCaller.obtainMessage(DO_DETACH);
   mCaller.sendMessage(msg);
 }
 @Override
 public void onRelayoutContainer() {
   Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
   mCaller.sendMessage(msg);
 }
 @Override
 public void destroy() {
   mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_DESTROY));
 }
 @Override
 public void moved(int newX, int newY) {
   Message msg = mCaller.obtainMessageII(MSG_WINDOW_MOVED, newX, newY);
   mCaller.sendMessage(msg);
 }
 public void restartInput(IInputContext inputContext, EditorInfo attribute) {
   mCaller.executeOrSendMessage(
       mCaller.obtainMessageOO(DO_RESTART_INPUT, inputContext, attribute));
 }
 public void hideSoftInput(int flags, ResultReceiver resultReceiver) {
   mCaller.executeOrSendMessage(
       mCaller.obtainMessageIO(DO_HIDE_SOFT_INPUT, flags, resultReceiver));
 }
 public void createSession(IInputMethodCallback callback) {
   mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CREATE_SESSION, callback));
 }
 @Override
 public void taskFinished(Intent intent, int taskId) {
   mHandlerCaller.sendMessage(
       mHandlerCaller.obtainMessageIO(MSG_TASK_FINISHED, taskId, intent));
 }
 @Override
 public void closeSystemDialogs() {
   mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_CLOSE_SYSTEM_DIALOGS));
 }
 @Override
 public void onUpdateSurface() {
   Message msg = mCaller.obtainMessage(MSG_UPDATE_SURFACE);
   mCaller.sendMessage(msg);
 }
 public void changeInputMethodSubtype(InputMethodSubtype subtype) {
   mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_CHANGE_INPUTMETHOD_SUBTYPE, subtype));
 }
 @Override
 public void taskStarted(Intent intent, int taskId) {
   mHandlerCaller.sendMessage(
       mHandlerCaller.obtainMessageIO(MSG_TASK_STARTED, taskId, intent));
 }