@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 handleMessage(Message msg) {
      switch (msg.what) {
        case MSG_GET_APP_PERMISSIONS:
          {
            SomeArgs args = (SomeArgs) msg.obj;
            String packageName = (String) args.arg1;
            RemoteCallback callback = (RemoteCallback) args.arg2;
            args.recycle();
            List<RuntimePermissionPresentationInfo> permissions = onGetAppPermissions(packageName);
            if (permissions != null && !permissions.isEmpty()) {
              Bundle result = new Bundle();
              result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, permissions);
              callback.sendResult(result);
            } else {
              callback.sendResult(null);
            }
          }
          break;

        case MSG_GET_APPS_USING_PERMISSIONS:
          {
            RemoteCallback callback = (RemoteCallback) msg.obj;
            final boolean system = msg.arg1 == 1;
            List<ApplicationInfo> apps = onGetAppsUsingPermissions(system);
            if (apps != null && !apps.isEmpty()) {
              Bundle result = new Bundle();
              result.putParcelableList(RuntimePermissionPresenter.KEY_RESULT, apps);
              callback.sendResult(result);
            } else {
              callback.sendResult(null);
            }
          }
          break;
      }
    }
 @Override
 public void handleMessage(Message message) {
   switch (message.what) {
     case MESSAGE_NOTIFY_MAGNIFIED_BOUNDS_CHANGED:
       {
         Region bounds = (Region) message.obj;
         try {
           mCallbacks.onMagnifedBoundsChanged(bounds);
         } catch (RemoteException re) {
           /* ignore */
         } finally {
           bounds.recycle();
         }
       }
       break;
     case MESSAGE_NOTIFY_RECTANGLE_ON_SCREEN_REQUESTED:
       {
         SomeArgs args = (SomeArgs) message.obj;
         final int left = args.argi1;
         final int top = args.argi2;
         final int right = args.argi3;
         final int bottom = args.argi4;
         try {
           mCallbacks.onRectangleOnScreenRequested(left, top, right, bottom);
         } catch (RemoteException re) {
           /* ignore */
         } finally {
           args.recycle();
         }
       }
       break;
     case MESSAGE_NOTIFY_USER_CONTEXT_CHANGED:
       {
         try {
           mCallbacks.onUserContextChanged();
         } catch (RemoteException re) {
           /* ignore */
         }
       }
       break;
     case MESSAGE_NOTIFY_ROTATION_CHANGED:
       {
         final int rotation = message.arg1;
         try {
           mCallbacks.onRotationChanged(rotation);
         } catch (RemoteException re) {
           /* ignore */
         }
       }
       break;
     case MESSAGE_SHOW_MAGNIFIED_REGION_BOUNDS_IF_NEEDED:
       {
         synchronized (mWindowManagerService.mWindowMap) {
           if (mMagnifedViewport.isMagnifyingLocked()) {
             mMagnifedViewport.setMagnifiedRegionBorderShownLocked(true, true);
             mWindowManagerService.scheduleAnimationLocked();
           }
         }
       }
       break;
       /// M:[ALPS01397351]Fix system server JE @{
     case MESSAGE_ON_ROTATION_CHANGED:
       {
         synchronized (mWindowManagerService.mWindowMap) {
           mMagnifedViewport.onRotationChangedLocked();
         }
       }
       break;
       /// @}
   }
 }
 @Override
 public void handleMessage(Message msg) {
   switch (msg.what) {
     case MSG_ADD_CONNECTION_SERVICE_ADAPTER:
       mAdapter.addAdapter((IConnectionServiceAdapter) msg.obj);
       onAdapterAttached();
       break;
     case MSG_REMOVE_CONNECTION_SERVICE_ADAPTER:
       mAdapter.removeAdapter((IConnectionServiceAdapter) msg.obj);
       break;
     case MSG_CREATE_CONNECTION:
       {
         SomeArgs args = (SomeArgs) msg.obj;
         try {
           final PhoneAccountHandle connectionManagerPhoneAccount =
               (PhoneAccountHandle) args.arg1;
           final String id = (String) args.arg2;
           final ConnectionRequest request = (ConnectionRequest) args.arg3;
           final boolean isIncoming = args.argi1 == 1;
           final boolean isUnknown = args.argi2 == 1;
           if (!mAreAccountsInitialized) {
             Log.d(this, "Enqueueing pre-init request %s", id);
             mPreInitializationConnectionRequests.add(
                 new Runnable() {
                   @Override
                   public void run() {
                     createConnection(
                         connectionManagerPhoneAccount, id, request, isIncoming, isUnknown);
                   }
                 });
           } else {
             createConnection(
                 connectionManagerPhoneAccount, id, request, isIncoming, isUnknown);
           }
         } finally {
           args.recycle();
         }
         break;
       }
     case MSG_ABORT:
       abort((String) msg.obj);
       break;
     case MSG_ANSWER:
       answer((String) msg.obj);
       break;
     case MSG_ANSWER_VIDEO:
       {
         SomeArgs args = (SomeArgs) msg.obj;
         try {
           String callId = (String) args.arg1;
           int videoState = args.argi1;
           answerVideo(callId, videoState);
         } finally {
           args.recycle();
         }
         break;
       }
     case MSG_REJECT:
       reject((String) msg.obj);
       break;
     case MSG_DISCONNECT:
       disconnect((String) msg.obj);
       break;
     case MSG_HOLD:
       hold((String) msg.obj);
       break;
     case MSG_UNHOLD:
       unhold((String) msg.obj);
       break;
     case MSG_ON_AUDIO_STATE_CHANGED:
       {
         SomeArgs args = (SomeArgs) msg.obj;
         try {
           String callId = (String) args.arg1;
           AudioState audioState = (AudioState) args.arg2;
           onAudioStateChanged(callId, audioState);
         } finally {
           args.recycle();
         }
         break;
       }
     case MSG_PLAY_DTMF_TONE:
       playDtmfTone((String) msg.obj, (char) msg.arg1);
       break;
     case MSG_STOP_DTMF_TONE:
       stopDtmfTone((String) msg.obj);
       break;
     case MSG_CONFERENCE:
       {
         SomeArgs args = (SomeArgs) msg.obj;
         try {
           String callId1 = (String) args.arg1;
           String callId2 = (String) args.arg2;
           conference(callId1, callId2);
         } finally {
           args.recycle();
         }
         break;
       }
     case MSG_SPLIT_FROM_CONFERENCE:
       splitFromConference((String) msg.obj);
       break;
     case MSG_MERGE_CONFERENCE:
       mergeConference((String) msg.obj);
       break;
     case MSG_SWAP_CONFERENCE:
       swapConference((String) msg.obj);
       break;
     case MSG_ON_POST_DIAL_CONTINUE:
       {
         SomeArgs args = (SomeArgs) msg.obj;
         try {
           String callId = (String) args.arg1;
           boolean proceed = (args.argi1 == 1);
           onPostDialContinue(callId, proceed);
         } finally {
           args.recycle();
         }
         break;
       }
     default:
       break;
   }
 }
  public void executeMessage(Message msg) {
    InputMethod inputMethod = mInputMethod.get();
    // Need a valid reference to the inputMethod for everything except a dump.
    if (inputMethod == null && msg.what != DO_DUMP) {
      Log.w(TAG, "Input method reference was null, ignoring message: " + msg.what);
      return;
    }

    switch (msg.what) {
      case DO_DUMP:
        {
          AbstractInputMethodService target = mTarget.get();
          if (target == null) {
            return;
          }
          SomeArgs args = (SomeArgs) msg.obj;
          try {
            target.dump((FileDescriptor) args.arg1, (PrintWriter) args.arg2, (String[]) args.arg3);
          } catch (RuntimeException e) {
            ((PrintWriter) args.arg2).println("Exception: " + e);
          }
          synchronized (args.arg4) {
            ((CountDownLatch) args.arg4).countDown();
          }
          args.recycle();
          return;
        }

      case DO_ATTACH_TOKEN:
        {
          inputMethod.attachToken((IBinder) msg.obj);
          return;
        }
      case DO_SET_INPUT_CONTEXT:
        {
          inputMethod.bindInput((InputBinding) msg.obj);
          return;
        }
      case DO_UNSET_INPUT_CONTEXT:
        inputMethod.unbindInput();
        return;
      case DO_START_INPUT:
        {
          SomeArgs args = (SomeArgs) msg.obj;
          IInputContext inputContext = (IInputContext) args.arg1;
          InputConnection ic =
              inputContext != null ? new InputConnectionWrapper(inputContext) : null;
          EditorInfo info = (EditorInfo) args.arg2;
          info.makeCompatible(mTargetSdkVersion);
          inputMethod.startInput(ic, info);
          args.recycle();
          return;
        }
      case DO_RESTART_INPUT:
        {
          SomeArgs args = (SomeArgs) msg.obj;
          IInputContext inputContext = (IInputContext) args.arg1;
          InputConnection ic =
              inputContext != null ? new InputConnectionWrapper(inputContext) : null;
          EditorInfo info = (EditorInfo) args.arg2;
          info.makeCompatible(mTargetSdkVersion);
          inputMethod.restartInput(ic, info);
          args.recycle();
          return;
        }
      case DO_CREATE_SESSION:
        {
          inputMethod.createSession(
              new InputMethodSessionCallbackWrapper(
                  mCaller.mContext, (IInputMethodCallback) msg.obj));
          return;
        }
      case DO_SET_SESSION_ENABLED:
        inputMethod.setSessionEnabled((InputMethodSession) msg.obj, msg.arg1 != 0);
        return;
      case DO_REVOKE_SESSION:
        inputMethod.revokeSession((InputMethodSession) msg.obj);
        return;
      case DO_SHOW_SOFT_INPUT:
        inputMethod.showSoftInput(msg.arg1, (ResultReceiver) msg.obj);
        return;
      case DO_HIDE_SOFT_INPUT:
        inputMethod.hideSoftInput(msg.arg1, (ResultReceiver) msg.obj);
        return;
      case DO_CHANGE_INPUTMETHOD_SUBTYPE:
        inputMethod.changeInputMethodSubtype((InputMethodSubtype) msg.obj);
        return;
    }
    Log.w(TAG, "Unhandled message code: " + msg.what);
  }