/**
   * Posts the specified command to be executed on the main thread, waits for the request to
   * complete, and returns the result.
   *
   * @see sendRequestAsync
   */
  private Object sendRequest(int command, Object argument) {
    if (Looper.myLooper() == mMainThreadHandler.getLooper()) {
      throw new RuntimeException("This method will deadlock if called from the main thread.");
    }

    MainThreadRequest request = new MainThreadRequest(argument);
    Message msg = mMainThreadHandler.obtainMessage(command, request);
    msg.sendToTarget();

    // Wait for the request to complete
    synchronized (request) {
      while (request.result == null) {
        try {
          request.wait();
        } catch (InterruptedException e) {
          // Do nothing, go back and wait until the request is complete
        }
      }
    }
    return request.result;
  }
    @Override
    public void handleMessage(Message msg) {
      MainThreadRequest request;
      Message onCompleted;
      AsyncResult ar;

      switch (msg.what) {
        case CMD_HANDLE_PIN_MMI:
          request = (MainThreadRequest) msg.obj;
          request.result = Boolean.valueOf(mPhone.handlePinMmi((String) request.argument));
          // Wake up the requesting thread
          synchronized (request) {
            request.notifyAll();
          }
          break;

        case CMD_HANDLE_NEIGHBORING_CELL:
          request = (MainThreadRequest) msg.obj;
          onCompleted = obtainMessage(EVENT_NEIGHBORING_CELL_DONE, request);
          mPhone.getNeighboringCids(onCompleted);
          break;

        case EVENT_NEIGHBORING_CELL_DONE:
          ar = (AsyncResult) msg.obj;
          request = (MainThreadRequest) ar.userObj;
          if (ar.exception == null && ar.result != null) {
            request.result = ar.result;
          } else {
            // create an empty list to notify the waiting thread
            request.result = new ArrayList<NeighboringCellInfo>();
          }
          // Wake up the requesting thread
          synchronized (request) {
            request.notifyAll();
          }
          break;

        case CMD_ANSWER_RINGING_CALL:
          answerRingingCallInternal();
          break;

        case CMD_SILENCE_RINGER:
          silenceRingerInternal();
          break;

        case CMD_END_CALL:
          request = (MainThreadRequest) msg.obj;
          boolean hungUp = false;
          int phoneType = mPhone.getPhoneType();
          if (phoneType == Phone.PHONE_TYPE_CDMA) {
            // CDMA: If the user presses the Power button we treat it as
            // ending the complete call session
            hungUp = PhoneUtils.hangupRingingAndActive(mPhone);
          } else if (phoneType == Phone.PHONE_TYPE_GSM) {
            // GSM: End all calls except waiting
            hungUp = PhoneUtils.hangupAllCalls(mPhone);
          } else {
            throw new IllegalStateException("Unexpected phone type: " + phoneType);
          }
          if (DBG) log("CMD_END_CALL: " + (hungUp ? "hung up!" : "no call to hang up"));
          request.result = hungUp;
          // Wake up the requesting thread
          synchronized (request) {
            request.notifyAll();
          }
          break;

        case CMD_INVOKE_OEM_RIL_REQUEST:
          request = (MainThreadRequest) msg.obj;
          onCompleted = obtainMessage(EVENT_INVOKE_OEM_RIL_REQUEST, request);
          mPhone.invokeOemRilRequestRaw((byte[]) request.argument, onCompleted);
          break;

        case EVENT_INVOKE_OEM_RIL_REQUEST:
          ar = (AsyncResult) msg.obj;
          request = (MainThreadRequest) ar.userObj;
          request.result = ar;
          // Wake up the requesting thread
          synchronized (request) {
            request.notifyAll();
          }
          break;

        case EVENT_UNSOL_OEM_HOOK_EXT_APP:
          ar = (AsyncResult) msg.obj;
          broadcastUnsolOemHookIntent((byte[]) (ar.result));
          break;

        case CMD_SET_TRANSMIT_POWER:
          request = (MainThreadRequest) msg.obj;
          onCompleted = obtainMessage(EVENT_SET_TRANSMIT_POWER_DONE, request);
          mPhone.setTransmitPower((Integer) request.argument, onCompleted);
          break;

        case EVENT_SET_TRANSMIT_POWER_DONE:
          boolean retStatus = false;
          ar = (AsyncResult) msg.obj;
          request = (MainThreadRequest) ar.userObj;

          if (ar.exception == null) {
            retStatus = true;
          }
          request.result = retStatus;

          // Wake up the requesting thread
          synchronized (request) {
            request.notifyAll();
          }
          break;

        default:
          Log.w(LOG_TAG, "MainThreadHandler: unexpected message code: " + msg.what);
          break;
      }
    }